表达式求值
1.整型提升
c语言中整型算数运算总是至少以默认整型的精度来进行的。为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升,按高位补。有符号整数提升是按照变量的数据类型的符号来提升的,无符号整数提升,高位补0.
int main()
{
char a = 5;
//00000000000000000000000000000101
//00000101截掉
char b = 126;
//00000000000000000000000001111110
//01111110
char c = a + b;转换两个整型
00000101--------a整型提升
//00000000000000000000000000000101
01111110--------b整型提升
//00000000000000000000000001111110
//运算:
//00000000000000000000000010000011
因为c为char
故再次截掉
//10000011-----c
//当以%d的形式打印的时候
//打印的是有符号整数
//这里对c发生整型提升
//按高位补,补1
//11111111111111111111111110000011----补码
//100000000000000000000001111100------取反
//100000000000000000000001111101-------原码
printf("%d\n",c);//-125
return 0;
}
算数转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型。否则操作就无法进行。小的转为大的数据类型。
表达式的学习
#include<stdio.h>
int fun()
{
static int count = 1;
return ++count;
}
int main()
{
int answer;
answer = fun()-fun()*fun();
printf("%d/n",answer);
return 0;
}
正常来说:值分别为2,3,4
故结果为-10
也可以3,2,4
为-5
这是因为调用的顺序不一样
故代码有错误
总结:即使有了操作符的优先级和结合性,我们写出的表达式依然有可能不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在潜在风险的,建议不要写出特别复杂的表达式。
指针
1.内存和地址
CPU在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中。把内存划分为一个个小的内存单元,一个单元为一个字节,每个字节都会有一个编号,该编号就是地址。而c语言中,编号称为指针
变量创建的本质是:是向内存申请空间 int a=10
指针变量
那我们通过取地址操作符(&)拿到的地址是一个数值,这个数值有时候也是需要储存起来,方便后期使用,那我们把这样的地址值存放在指针变量中。指针变量也是一种变量,这种变量就是用来存放地址的,存放在指针变量中的值都会理解为地址。
int main()
{
int n = 20;
char ch = 'w';
//pn 就被成为指针变量
int *pn = &n;
return 0;
}
&n----n的地址------地址就是指针
pn = &n;
pn就是用来存放地址的,也可以说是用来存放指针的
pn 就可以被称为指针变量
pn的类型是:int*,*------说明pn是指针变量
int----说明pn指向的对象是int类型的
解引(间接访问)用操作符(*)
c语言中,我们只要拿到地址(指针),就可以通过指针找到指针指向的对象。
int main()
{
int a = 100;
int*pa = &a;
//间接访问操作符
*pa = 0;//取地址操作符(&)与间接访问操作符 (*) 抵消(单目操作符)
return 0;
}
*pa其实就是a变量
指针变量的大小
32位(x86)机器上,有32根地址线,一个地址是32个二进制,4个字节就能储存,指针变量大小就是4个字节
64位(x64)机器上,有64根地址线,一个地址是32个二进制,8个字节就能储存,指针变量大小就是8个字节
指针变量的大小和类型是无关的,只要指针类型的变量,在相同平台(x64)下,大小都是相同的。
这里指针类型决定:在对指针进行解引用操作的时候,访问几个字节
char*------解引用访问1个字节
int*--------解引用访问4个字节
指针的类型决定了指针向前或者向后走一步有多大距离
void*指针(是无具体类型的指针)(或叫泛型指针)
可以接受任意类型的指针,但是要有局限性,void*类型道德指针不能直接进行的+-整数和解引用的运算
int main()
{
int a = 10;
char*pc = &a;//它是会报错的
void*pi = &a;//则不会报错
*pi = 20;//局限性
pi + 1;//局限性
return 0;
}
int main()
{
int a = 10;
void*pc = &a;
*(int*)pc = 200;//强制转换
printf("%d\n",n);//200
return 0;
}