绝代码农 发表于 2021-7-22 23:32:19

c语言_Day21_07_22

1、表达式求值
表达式求值需要注意两部分内容:优先级顺序和类型转换
1、类型转换

[*]隐式类型转换

[*]整形提升:表达式中的字符和短整形操作数在使用之前被转换为普通整形
int main()
{
char a = 3;
char b = 127;
char c = a + b;
printf("%d", c);
return 0;
}
[*]当用a(b)存放3(127)时,a(b)的空间大小为1byte,而3(127)的数据大小为4byte,故数据需要发生截断
[*]字符相加需进行整形提升(按数据类型的符号位进行提升),再计算
[*]将计算结果存放至c中,c的空间大小位1byte,而结果为整形,故数据需要截断
[*]打印整形,故c发生整形提升,得到补码,再转至原码打印
整型提升补充数据规则:

[*]正数补零
[*]负数补一
[*]无符号数补零
验证整形提升:int main()
{
        char a = 0xb6;
        short b = 0xb600;
        int c = 0xb6000000;
        if (a == 0xb6)
        {
                printf("a");
        }
        if (b == 0xb600)
        {
                printf("b");
        }
        if (c == 0xb6000000)
        {
                printf("c");
        }

        return 0;
}只有在算术运算符、位运算符和关系运算符的计算中发生整形提升

[*]算术转换:对于存储空间大于int的数据类型,进行计算时应转换为存储空间较大的数据类型再执行计算
long double

double

float

unsigned long int

long int

unsigned int

int2、优先级

[*]操作符优先级(高 -> 低)
[*]结合性
() 聚组 NR

() 函数调用 LR

[] 下标引用 LR

. 访问结构成员 LR

-> 访问结构指针成员 LR

++ 后自增 LR

– 后自减 LR

! 逻辑取反 RL
按位取反 RL
+ 单目,表示正值 RL

- 单目,表示负值 RL

++ 前自增 RL

– 前自减 RL

* 解引用 RL

& 取地址 RL

sizeof RL

(类型转换) RL

* 乘法 LR

/ 除法 LR

% 取余 LR

+ 加法 LR

- 减法 LR

<< 左移 LR

>> 右移 LR

> 大于 LR

>= 大于等于 LR

< 小于 LR

<= 小于等于 LR

== 等于 LR

!= 不等 LR

& 按位与 LR

^ 异或 LR

| 按位或 LR

&& 逻辑与 LR

|| 逻辑或 LR

?: 三目表达式 NR

= 赋值(赋值操作符)RL

, 逗号表达式 LR

[*]控制求值顺序(是否存在短路逻辑)
问题表达式:在已知优先级、结合性等性质下仍无法给出唯一解的表达式(以下均为问题代码)
// 表达式1
a*b + cd - ef
// 表达式2
c + --c
// 表达式3
int main()
{
int i = 10;
i = i-- - --i * ( i = -3 )i++ + ++i;
printf("%d\n", i);
return 0;
}
// 表达式4
int foo()
{
static int count = 1;
return ++count;
}

int main()
{
int res = foo() - foo()foo();
printf("%d\n", res);
return 0;
}
// 表达式5
int main()
{
int i = 1;
int res = (++i) + (++i) + (++i);
printf("%d\n", res);
printf("%d\n", i);
return 0;
}2、指针基础
1、基本概念
指针:一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值
内存理解:一块内存可被分为数块空间,每块空间最好存放1字节大小;每块空间对应一个编号,作为该内存单元的唯一标识
指针变量:存放变量的内存地址的变量
地址线:对于32位的机器,共有32根地址线,地址线每次寻址可产生一个电信号(+/-),故32根地址线一共可产生2^32次方个地址
指针大小:在32位机器上,地址为32个0或1组成的二进制序列,故需要通过4byte大小存储;在64位机器上,地址由64个0或1组成的二进制序列,故需要通过8byte大小存储
编址大小:对于32位机器,通过32个0或1组成的二进制序列存放地址,共有2^32种排列组合可能,又知每块内存单元存放1字节大小,故可计算得共有2^32byte = 2^22 KB = 2^12MB = 4GB编址
2、指针类型
虽然不同类型的指针存放大小相同,但不同类型的指针本质上并不相同
指针类型决定了:

[*]指针解引用时能够访问的空间的大小(int可访问4byte,char\可访问1byte)
int main()
{
double d = 3.14;
int* p = &d;
p = 0;
return 0;
}
[*]指针的步长(指针走一步的长度)
int步长为4;char步长为1;double\步长为8
int main()
{
int a = 0x11223344;
int* pa = &a;
char pc = &a;
printf("%p\n", pa);
printf("%p\n", pa + 1);
printf("%p\n", pc);
printf("%p\n", pc + 1);
return 0;
}3、野指针
野指针:指针指向的位置不可知(随机的、不正确的、没有明确限制的)
野指针成因:

[*]指针未初始化
int a;
int p = &a;
[*]数组越界访问
int arr = {0};
int* p = arr;
for(int i = 0; i < 11; i++)
{
(p++) = i;
}
[*]指针指向的内存空间释放
int test()
{
int a = 0;
return &a;
}
int main()
{
int* p = test();
return 0;
}野指针避免:

[*]指针初始化
[*]防止指针越界
[*]指针指向空间释放及时置为NULL(注:NULL本质为(void )0)
[*]检查指针指向的有效性

4、指针运算

[*]加减整数
指针与整数加减运算一般用于数组,其加减操作可理解为更改指针所指向的数组元素
int main()
{
        int arr = { 1, 2, 3, 4, 5 };
        int length = sizeof arr / sizeof arr;
        int* p = &arr;
        for (int i = 0; i < length; i++)
        {
                printf("%d\n", *(arr + i));
        }
        printf("=======================\n");
        for (int i = 0; i < length; i++)
        {
                printf("%d\n", *(p - i));
        }

        return 0;
}#define N_VAL 5
int main()
{
        float values;
        float* vp;
        for (vp = &values; vp < &values;)
        {
                *vp++ = 0;
        }

        return 0;
}
[*]加减指针
指针减指针为中间元素的个数例:三种方法实现strlen函数 //循环法
int my_strlen(char str[])
{
        int count = 0;
        char* p = str;
        while (*p)
        {
                count++;
                p++;
        }
        return count;
}

// 递归法
int my_strlen(char str[])
{
        if (str)
        {
                return my_strlen(str + 1) + 1;
        }
        else
        {
                return 0;
        }
}

// 指针间运算法
int my_strlen(char str[])
{
        char* start = str;
        char* end = NULL;
        while (*str)
        {
                str++;
        }
        end = str;
        return end - start;
}
文档来源:51CTO技术博客https://blog.51cto.com/u_15285915/3169819

页: [1]
查看完整版本: c语言_Day21_07_22