1字符串和指针串讲
p[-2] 等价于:*(p - 2) 得到的是main()中数组元素ch[0]的值,而这个值是指向字符串"apple"的指针。 它接收到"apple"的首字符地址。
********数组名遇到sizeof,通常 计算整个数组;数组名参与普通表达式,通常退化为指针。
*********一级指针、二级指针、三级指针通常都是8 字节。
2.大小端
uint32_t x = 0x12345678;
知识点uint32_t32位 占4 字节,因此这个数会拆成4 个字节
&x:获取变量x的起始地址。(unsigned char *):将地址转换为字符指针。p[0]:访问从起始地址开始的第 1 个字节。p[3]:访问从起始地址开始的第 4 个字节。
注意:这里的p是unsigned char *,因此p + 1移动的是1 个字节,不是 4 个字节。
uint16_t a[3] = {0x1234, 0x5678, 0x9ABC};
uint16_t占2 字节,数组有3 个元素
数组元素还是按顺序放a[0] a[1] a[2]
3.json配置补充
4.unsigned int和int进行运算
当unsigned int和int进行运算时,在常见的 32 位int、32 位unsigned int环境下,int会转换成unsigned int。
5.联合体补充知识点
联合体union中,不管访问第几个成员,所有成员都是从同一个 内存起始地址开始的。
例:
union {
int i;
char c[4];
} u; (它定义了一个没有 标签名的联合体类型,并同时创建变量u。)
u.i:访问整个整数。u.c[0]:访问第一个字节。u.c[1]:访问第二个字节。u.c[2]:访问第三个字节。u.c[3]:访问第四个字节。
联合体 类型名可以省略,但这里的变量名u不能省略。
1.联合体每个都打分号 2.要声明 联合体变量
6.编写 MAX(a, b),避免参数副作用
#define MAX(a, b) ({ \
__auto_type max_a = (a); \
__auto_type max_b = (b); \
max_a > max_b ? max_a : max_b; \
})
int result = MAX(x++, y++);这个题考的是怕x++执行两次 就把他们的值保存起来 进行比较 返回值的大小
编写一个宏SWAP(type, a, b)交换两个同类型变量,要求能够像函数一样后跟分号
#define SWAP(type, a, b) \
do { \
type *_pa = &(a); \
type *_pb = &(b); \
type _temp = *_pa; \
*_pa = *_pb; \
*_pb = _temp; \
} while (0)为什么写成 do while(0)?因为后面要加个分号 文本替换后 只有do while语句加个分号才刚好是完整句型
do { /* 多条语句 */ } while (0) ;传指针怕里面传的两个数组,交换后,数组里的值多次移动,给他第一步的值先保存下来、
你使用的pa、pb、temp都是宏内部的局部变量,但如果调用时恰好使用了同名变量,就可能发生名称冲突。
因此,建议使用更有辨识度的临时变量名
7.inline
向编译器建议,尽可能把函数的代码直接放到调用的位置,减少函数调用的开销。
#include <stdio.h>
3. 为什么传®?
reg是变量,®是它的地址。函数接收地址后,通过*reg直接修改原变量。
static inline则表示建议编译器考虑内联优化;它不会改变函数的置位、清零逻辑。
8.memmove()
memmove():负责复制,并且允许源和目标内存重叠。
size_t len = strlen(src) + 1;
memmove(dest, src, len);
dest:目标内存的起始地址。src:源内存的起始地址。len:复制的字节数(strlen(src) + 1),包含最后的'\0'。
9.size_t
10.calloc()
calloc()会把申请到的内存全部初始化为0。
calloc()是 C 语言标准库<stdlib.h>中的动态内存分配函数。
calloc(元素个数, 每个元素的大小);
11.free()
free()释放的是之前通过动态内存分配函数申请的内存,而不是释放变量本身。
12.static和extern
只有 外部链接,可以通过extern声明访问。