1)3.14的理解
int a = 3.14; int b = 3.14f;
3.14在第一行中被默认为double类型,会进行强制类型转换,截断小数点后的数据。
3.14在第二行中加上了f,意为float类型,同样会进行强制类型转换,截断小数点后的数据。
2)sizeof是操作符
int a = 10;
printf("%d", sizeof a);
这样是可以正常输出4的。而函数的参数必须要在括号中,这样就说明了 sizeof 只是操作符。
strlen()是库函数。是用来求字符串长度的一个库函数,并不包含 '\0 '的长度。
3)字符指针的大小
void fun(char* a){printf("%d", sizeof(a));}
int main(){char a = { 0 };fun( a );
}
发现是8(因为我是x64),而不是1(因为字符在内存中占1个字节)。无论是哪种指针都是一样的,都存放的是地址,与char无关。
4)字符串的比较
if ("abc" == "abcdef"){}
这其实是在比较两个字符串的首元素地址是否相同。两个字符串比较相等应该使用strcmp()函数。
5)通过位操作符交换两个数据
0 ^ a = a
a ^ a = 0
a ^ a ^ b = a ^ b ^ a
以上是按位操作的一些特点。
1 int a = 3, b = 4; 2 a = a ^ b; 3 b = a ^ b; 4 a = a ^ b;
这样就可以实现两个数的交换。
原理为:
1. a = a ^ b
2. b = a ^ b ^ b = a
3. a = a ^ b ^ a =a ^ a ^ b = 0 ^ b = b
6)赋值操作符是在创建变量之后的
int a = 3; a = 9;
第一行为初始化,并非赋值操作。第二行的等号才是赋值操作符。
7)警惕自增和短路的结合
int a = 3, b = 4, c; c = a++ || ++b;
b其实没有自增,因为a为真之后,后半句直接短路了。
同样需要注意是是前缀自增还是后缀自增,一个是先递增再判断,一个是先判断再递增。
8)隐式类型转换
C的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
无符号整型提升没有影响。因为前面都补0,没有任何数值上的影响。
放在表达式里的short,char达不到int,都会发生整型提升。
1 #include <stdio.h> 2 int main() { 3 char a = 1; 4 printf("%zd\n", sizeof(+a)); 5 printf("%zd\n", sizeof(-a)); 6 printf("%zd\n", sizeof(a)); 7 }
可以发现4,5行的输出结果是4,因为参与了表达式运算,整型提升为了int。
整形提升是按照变量的数据类型的符号位来提升的

意思就是符号位是什么,提升出来多的就填什么。
#include <stdio.h> int main() {char a = -1;char b = 16;//也就是说 -1 作为 32 位整数,先变成补码,再被截断。//1000 0000 0000 0000 0000 0000 0000 0001(原)//1111 1111 1111 1111 1111 1111 1111 1110(反)//1111 1111 1111 1111 1111 1111 1111 1111(补)// //0000 0000 0000 0000 0000 0000 0001 0000(补)//存储在char中为://1111 1111//0001 0000//在计算中提升为:// 1111 1111 1111 1111 1111 1111 1111 1111//+ 0000 0000 0000 0000 0000 0000 0001 0000//= 0000 0000 0000 0000 0000 0000 0000 1111(补)//同样的,先获得补码运算结果,再截断//截断后为://0000 1111(反反补) //char为有符号数 答案就是15char c = a + b;printf("%d", c); }
9)算数转换:int及以上的情况
long double
double
float
unsigned long int
long int
unsigned int
int
操作符运算过程中,如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。