union data {
short st;
char cs[2];
};
int main() {
union data x = {};
x.st = 0x0001;
if (x.cs[1] == 0) {
// 高地址存放高位
printf("小端\n");
}
else {
printf("大端\n");
}
return 0;
}
union data {
char ch; // 1 + 3
// 哑元结构
union { // 4
float f;
int i;
};
};
int main() {
printf("%ld\n", sizeof(union data)); // 4
return 0;
}
// 此时data1有2个成员,ch和联合体
struct data1 {
char ch; // 1 + 3
union {
// 4
float f;
int i;
};
};
// 当类型里嵌套类型的时候,内部类型和外部类型没有关系,只是在设计的时候采用这种方案
// 可以通过外部类型的变量访问内部类型的变量,但是从内存角度而言这个内部变量并不属于外部变量
struct data2 {
//data2只有1个成员
char ch;
union udata{
float f;
int i;
};
};
int main() {
printf("%ld\n", sizeof(struct data1)); // 8
printf("%ld\n", sizeof(struct data2)); // 1
struct data2 x;
x.udata = 12; // 这句报错,无法直接访问
union data2::udata xx; // 通过作用域定义
return 0;
}
union IPNode {
unsigned int addr;
char s3, s2, s1, s0;
};
int main() {
union IPNode x;
x.addr = 0x61626364;
char ch = x.s0;
printf("%x\n", ch); // 64
ch = x.s1;
printf("%x\n", ch); // 64
ch = x.s2;
printf("%x\n", ch); // 64
ch = x.s3;
printf("%x\n", ch); // 64
return 0;
}
注:写成数组的形式,使得内存连续分配,才可得到64、63、62、61
char* getString() {
char str[] = { "hello" };
return str;
}
int main() {
char* str = getString(); // 函数执行完成后,数组str被销毁,str成为失效指针,地址可访问
printf(str); // 打印随机值
strcpy_s(str, 10, "hello"); // 一般而言,str指向空间失效,但是地址有效,应该是可以赋值
printf(str);
free(str); // 只有根据malloc的头尾信息进行free
return 0;
}
char* getString() {
char* str = "hello"; // 分配至全局区,而不在栈区
return str;
}
int main() {
char* str = getString(); // 函数执行完成后,全局区的"hello"不会被销毁
printf(str); //打印hello
strcpy_s(str, 10, "hello"); // 无法赋值,字符串常量可读不可写
return 0;
}
int main() {
int* p = (int*)malloc(sizeof(int));
*p = 100;
printf("%d\n", *p); // 正常打印
free(p); //free后变成失效指针,将已用标记改成未用标记,但是地址依然有效(野指针的地址无效)
// 失效指针地址有效,不为0
if (NULL != p) {
printf("%d\n", *p); // 随机值
*p = 200; // 正常赋值
printf("%d\n", *p); // 正常打印
}
free(p); // 重复free,报错
return 0;
}
int main() {
int* p = (int*)malloc(sizeof(int));
int* s = NULL;
*p = 100;
printf("%d\n", *p);
free(p); // 从堆区释放内存,地址还存在,只是存放的数据变成了随机值
s = (int*)malloc(sizeof(int)); // 这里申请的是和p一样的地址
*s = 200;
printf("%d\n", *p); //正常打印
free(p); // 通过p把s释放,因为p和s的地址相同
free(s); // 同一地址重复释放,报错
return 0;
}
野指针就是不知道指向哪里,或者说不知道指向的内存是否可以使用,一般都是刚刚声明但没有初始化的指针。空指针不是指向常数0,只指向地址0,即NULL,其实换句话说,指针的本质就是地址嘛,空指针就是指针本身的值(地址)为0空指针的作用是防止野指针的出现,因为我们不能知道野指针到底指向哪里,所以我们也无法判断一个指针是否是野指针,这样很危险,但如果养成将指针初始化为空指针的习惯,我们就能判断出这个指针是不是有效的
union B {
unsigned int a;
unsigned char b[4];
}g;
int main() {
g.b[1] = 1;
printf("%d, %d\n", sizeof(union B), g.a);//4, 256
return 0;
}
int get_sys_mode1() {
union{
unsigned int a;
unsigned char b[4];
}g;
g.a = 1;
return g.b[3] == 1;// b[3]是高地址,1是低位
}
int get_sys_mode2() {
int a = 1;
int* p = &a;
return (*(char*)p) == 0;
}