sizeof

sizeof 用法比较奇特,可以用于数据类型,也可以用于变量。

  1. 数据类型

    用于数据类型就是用查看在本机上各个数据类型所占用的字节数。

    //只有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而言,是所有成员的总长度。但是可能出现不相等的情况,可能是由于对齐的问题。

  2. 用于变量

数组

对于数组,本应该是可以获取到数组大小的,我们也可以通过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 都失效了。