C语言重点总结
指针
就 c 语言的数组与函数, 我有一定理解, 总结如下 a[i]==i[a]==*(a+i) ()为根据地址执行指令
type&action | object | function | array |
---|---|---|---|
值/name | 值 | 函数地址 | 首元素地址 |
& | 变量地址 | 函数地址 | 数组地址 |
* | 值所代表的地址上的值 | 函数地址 | 首元素 |
sizeof | type'size | no | (sizeof type)*length |
c 与 c++
- C++认为 int fun()==int fun(void), C 认为只是省略了
- C 的 char 常量'a'是 int 类型, 因此'ABCD'不会报错
- C++的 const 变量默认是内部链接, 可以用 extern 改为外部链接
- C++const 变量可以初始化 const, C 不行
- C++严格使用枚举, C 将之认定为整型
- C++原生宽字符, C 原生复数
- C++11 没有初始化器, restric, VLA, 伸缩型数组成员, 可变数量参数的宏
- c 标记名与变量名可以重复, c++不行
- molloc 在 C++中必须强制类型转换
- C 警告将 const 指针赋给普通指针, C++error
- C++可以用 const 整型声明数组大小
- C++可以 type(name)强制类型转换
- C++不可调用 main()现在 C 也不行了
- C 可以 char[3]="asd"
以上受时间影响, 仅供参考
声明
构成:type name+修饰符 不讨论 const extern 等
修饰符有三种:
- 后置有[]与(), 优先级相同, 自左向右结合 当然, 这是对规律的总结, 实际上它们不是运算符, 没有优先级与结合律
- 前置* 优先级小于后置, 因此我们声明数组与函数的指针必须使用()
将修饰符与 name 结合, 理解它的类型 最后你会发现, 如果你将以上三种符号认为是运算符形式, 那么你得到的是一个表达式, 而前面的 type 就是表达式值的类型
链接数组
这是一个值得被单独拿出来说的事情 在链接阶段跨文件使用一个全局数组的时候 不能 extern 一个指针 (反之函数形参可以) 因为链接变量是指出 a 的地址 (由另一个文件定义), 当你把一个数组声明为对应元素的指针, 会认为数组地址存储的那个值是指针的值, 本质原因是数组的值虽然是首元素的指针, 但没有使用额外的空间存储, 程序会访问未知的内存
增补
C 标准中的概念
- 1byte >= 8bit
- 函数最少支持 31 个参数
- 一条代码行里至少可以有 509 个字符
- 表达式中, 至少支持 32 层嵌套()
- 至少 257 个 case
- 对象指一个或多个字节, 这些字节的二进制值为对象表示, 对象表示中可能含有填充
对象类型
- 大小与对齐要求
- 算术类型, 标准有符号整数类型大概率没有填充
- _BitInt(n) 类似 n 位有符号整数类型, 但可能有填充
- 无符号去掉符号位
- 派生类型:数组/函数(不是对象类型)/指针/结构/联合/原子
- 数组类型, T[n], 要求 T 是完全对象类型, T[]为不完全对象类型, 若 N 为整数常量/整数常量表达式, 则 T[n]为普通数组类型, 否则为变长度数组类型
- 指针类型
- 限定类型, const/volatile/restrict(只能修饰指针/指针多维数组, 含义仅我所有)/_Atomic
- 算术类型与指针类型(包括 nullptr_t)及其限定类型为标量类型
- 初始化: name={};name=值;name=除
,
表达式外的任何 16 种表达式 - 具名对象与匿名对象
- 对象属性:地址/类型/对齐要求/大小/表示值/表示类型/对象名称
- 分配对象的方式:声明/字符串/内存管理/复合字面量