杂记 define,typedef,static,extern,memset,ifndef,递归,逻辑与&&,整型提升,算术转换,栈区,高地址,数组越界访问
·
目录






有符号无符号所占的字节是一样的
常量,define







typedef

static extern


static 局部变量:
-
只在第一次进入函数时执行初始化
-
之后不再初始化,而是保留之前的值
-
生命周期贯穿整个程序运行期(和全局变量一样)








声明一下就可以用了 ,函数的外部链接属性,外部链接属性的意思是,外部的其它源文件,只要想使用这个函数extern声明一下就可以了


该函数只能在自己的源文件使用。





#define定义常量和宏


指针


操作系统,网络


system执行系统命令
memset


ifndef
避免头文件被引好多次 ,比如都引了#include<stdio.h>,这个头文件有1000行,都引,那不就是好几千行,重复了

当别人在包含add.h时都会先判断if没有定义它,第一次引add.h头文件时已经定义了,所以别人第二次在引用add.h,#endif前面的代码都不会执行。
防止同一个头文件被重复引用多次。_ADD_H_一般都是根据头文件的名字写的

递归

冒泡排序

单目操作符

逻辑与&&
左边是假,右边不管是什么都不算了

隐式类型转换
整型提升
无符号数整型提升补零,有符号数整型提升补符号位。






char a = 0xb6;
short b = 0xb600;
int c = 0xb6000000;
if (a == 0xb6) {
printf("a");
}
if(b == 0xb600) {
printf("b");
}
if (c == 0xb6000000) {
printf("c");
}




算术转换






栈区

高地址

数组越界访问
内存中没有“结构体”的概念
-
在计算机内存里,只有 一串连续的字节(0 和 1)。
-
内存里不会自动标记“这里是一个结构体,这里是字段”。
-
结构体是 C 编译器的一个概念,用来告诉编译器“按某种布局去访问这段连续内存”
例子1:结构体
#include <stdio.h>
#include <string.h>
// 取消结构体对齐
// 否则的话item会对齐到自己最大对齐数的整数倍的地方
#pragma pack(1)
typedef struct {
int opIdx;
int mlbType;
} Item;
typedef struct {
unsigned short cnt;
Item item[5];
} CellUeInstMlb;
# pragma pack()
int main(void) {
CellUeInstMlb msg;
// 模拟从外部收到消息,但cnt=0,表示数组里没有有效元素
msg.cnt = 0;
// 内存里虽然有 item 数组空间,但逻辑上没有“有效数据”
// 打印看看地址关系
printf("unsigned short所占字节:%d\n", sizeof(unsigned short));
printf("msg addr = %p\n", &msg);
// 因为第一个元素相对于结构体的偏移量是0
printf("msg->cnt addr = %p\n", &((&msg)->cnt));
// opIdx相对于结构体偏移2个字节,从这个地方开始取出4个字节的数据
printf("msg.item[0].opIdx addr = %p\n", (void*)&msg.item[0].opIdx);
// ⚠️ 错误做法:直接访问 item[0]
printf("错误访问:opIdx = %d\n", msg.item[0].opIdx); // 未定义行为!
// ✅ 正确做法:先判断 cnt
if (msg.cnt > 0) {
printf("正确访问:opIdx = %d\n", msg.item[0].opIdx);
} else {
printf("cnt == 0,跳过访问 item[0]\n");
}
return 0;
}
/*
内存确实是连续的(你可以看到 msg 和 msg.item[0] 的地址相邻)。
msg.item[0].opIdx 实际只是“偏移到那个位置去取 4 个字节的数据”。
因为我们没初始化它,所以打印出的是 垃圾值。
这就是“未定义行为”:可能打印垃圾、可能崩溃、也可能看似正常。
*/

C 编译器在编译阶段就知道每个字段的偏移量和大小。
这些信息不是运行时计算的,而是编译时确定的。
运行时并不知道“结构体”这个概念,它只看地址和字节数。



.、->、数组下标 [] 其实都是编译器帮你计算偏移量,然后取对应内存的语法糖
-
.字段或->字段[]都只是编译器帮你做的偏移计算 + 类型转换。
最终都是内存地址 + 偏移量 → 取对应字节




例子2
#include <stdio.h>
#include <string.h>
int main(void) {
int a[5] = {1, 2, 3, 4, 5};
for (int i = 0; i <= 5; i++) {
// 然后从该地址读取 4 字节并解释为 int
printf("%d\n", a[i]);
}
return 0;
}



更多推荐


所有评论(0)