sizeof
sizeof 用法比较奇特,可以用于数据类型,也可以用于变量。
-
数据类型
用于数据类型就是用查看在本机上各个数据类型所占用的字节数。
//只有char相关是确定的1字节,其他都根据实际机器而定。 sizeof(char) = 1; sizeof(unsigned char) = 1; sizeof(signed char) = 1; //依据实际情况而定 sizeof(int) = 4; sizeof(unsigned int) = 4; sizeof(short int) = 2; sizeof(unsigned short) = 2; sizeof(long int) = 4; sizeof(unsigned long) = 4; sizeof(float) = 4; sizeof(double) = 8; sizeof(long double) = 12;对于union而言,是成员字节最长长度。
对于struct而言,是所有成员的总长度。但是可能出现不相等的情况,可能是由于对齐的问题。
-
用于变量
数组
对于数组,本应该是可以获取到数组大小的,我们也可以通过int s[10]="123";printf("len:%d",sizeof(s));来获得len:10的结果。
所以,数组变量应该不仅仅包含数组首地址信息,还是包括数组大小信息的。
但是当发生函数传递时,数组变量似乎发生了退化,它好像变成了一个单纯的数据指针,所以如果想合理利用该数组,还需要向应用函数传入数组大小信息。
退化的原因在于发生了隐式转换,由数组变成了数据指针;如果需要避免这种情况,可以显式地提取数组指针。指针总不会变吧
// x_ptr现在指向了数组的第一个元素(即整数20).
// 这是因为数组通常衰减为指向它们的第一个元素的指针。
// 例如,当一个数组被传递给一个函数或者绑定到一个指针时,
//它衰减为(隐式转化为)一个指针。
// 例外: 当数组是`&`操作符的参数:数组的初始化:可以用字符串"abcdef",也可以用大括号括起来的数组{1,2,3,4,5},对于多维数组,就多用几个大括号int arr[2][2]={{1,2},{3,4}}。比较好奇为什么不用中括号
函数声明
如果函数调用在main()之后,那么必须声明在main()之前
浮点数
浮点数和浮点运算都是近似运算。
布尔类型
c中没有布尔类型,只有0和非0。
所以!3的结果为0,但是一般默认(!0)==1
移位操作
对有符号整数进行移位操作要小心 —— 以下未定义:
- 有符号整数位移至符号位 int a = 1 << 32
- 左移位一个负数 int a = -1 << 2
- 移位超过或等于该类型数值的长度
- int a = 1 << 32; // 假定int32位
循环
循环里面必须有语句,如果需要为空语句,填写分号;即可`。
switch分支
标签必须为整型数据
类型转换
类型转换可能存在溢出,且不会报异常。char a=257;那么a==1。
指针
指针的格式化表示为%p
外部、内部
外部关键词:extern;内部关键词:static
typedef
类型定义的语法可以归结为一句话:只要在变量定义前面加上typedef,就成了类型定义。这儿的原本应该是变量的东西,就成为了类型。这个变量名就变成了类型。
函数指针
类似函数声明的写法:int (*func)(int,int);,如果要定义某一函数指针类型,依据typedef用法:typedef int (*func)(int,int),则func变成一个函数指针类型。
动态分配内存
分配内存有三种:malloc,calloc,realloc
void *malloc(size_t size);malloc函数为长度size的对象分配内存,并返回指向分配区域的指针;若无法满足要求,则返回NULL。该函数不对分配的内存区域进行初始化。
void *calloc(size_t nobj, size_t size);calloc函数为由nobj个长度为size的对象组成的数组分配内存,并返回指向分配区域的指针;若无法满足要求,则返回NULL。分配 成功后 ,空间初始化为0,
void *realloc(void *p, size_t size);realloc函数将p指向的对象的长度修改为size个字节。如果新分配的内存比原来内存大,则原内存的内容会拷贝到新的内存空间,新增加的空间不进行初始化。如果新分配的内存比原来的内存小,则分配内存单元不初始化,realloc函数返回指向新分配空间的指针,原有的内存的空间会被释放;若无法满足要求,则返回NULL。在这种情况下,原来指针p指向的单元内容保持不变。一定要注意,如果调用成功后,原有的内存空间和指针p 都失效了。