ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

C语言补充3

C语言补充3

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是变量,&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声明访问。

13.结构体

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进