c语言|C语言结构体中的成员数组与指针的区别
文章目录
- 前言
- 问题
- NULL指针
- 分析代码一
- 分析代码二
- 结构体中的指针与数组差别
- 分析代码三
- 分析代码四
- 分析前面问题
- 总结
前言
1.博主实力有限,博文有什么错误,请你斧正,感谢! |
---|
2.本文借签陈皓的文章:《C语言结构体中的成员数组与指针》 |
#include
struct str{int len;
char s[10];
};
struct foo {struct str *a;
};
int main(int argc, char** argv) {struct foo f={
0};
if (f.a->s) {printf( f.a->s);
}
return 0;
}
NULL指针
- 请问本题错在什么地方?为什么?
- f.a被初始化为空了嘛,用空指针访问成员变量为什么不crash(崩溃)?
- 如果你不是太清楚,希望本片博客能对你有帮助!
分析代码一
- NULL指针 赋值给任何指针时,其实编译器都隐含的将NULL(0)转化为对应的地址。
struct s * p=NULL;
这 里 NULL 隐含转化为 结构体地址。
- NULL指针分配的分区:其范围是从 0x00000000到0x0000FFFF。这段空间是空闲的,对于空闲的空间而言,没有相应的物理存储器与之相对应,所以对这段空间来说,
任何读写
操作(解引用)都是会引起异常的。空指针是程序无论在何时都没有物理存储器与之对应的地址。为了保障无论何时
这个条件,需要人为划分一个空指针的区域,固有上面NULL指针分区.
- 虽然NULL指针不能进行任何
解引用
操作,但是进行比较或者运算是可行的。见代码
文章图片
文章图片
分析代码二
- 可以看出t的地址与t.i地址相同,而 t.p的地址 与t,i的地址相差4字节。
- 【c语言|C语言结构体中的成员数组与指针的区别】实际t.i,t.p的地址就是 (&t+0x00),(&t+0x04).
- 0x00,0x04,这是i与p相对于 结构体实例的相对地址,这于结构体的内存对齐中的偏移量有关。
- 因此 我们知道:不管结构体的实例是什么——访问其成员其实就是结构体变量的地址加成员的相对地址。
- 但是如果t的地址恰好为 NULL呢?—
文章图片
结构体中的指针与数组差别
- 这里 t的地址不同于t.i的地址是因为,指针的地址和指针指向数据地址的区别。
- 因此从代码一中我们知道,t.i的地址(&t+0x00)。但是这里 &t=0.因为 NULL指针可以进行运算,因此t->i与t->p的地址是 0x00000000,0x00000004;
文章图片
分析代码三
- 观察 汇编代码可以知道 ,(结构体中是同样道理)
- 对于数组名来说,汇编使用的是 lea(load effective address),将地址放到寄存器中
- 对于指针来说,汇编使用的是mov ,这是将指向的地址放带寄存器中。
- 因此在 访问成员数组名其实得到的是数组的相对地址,而访问成员指针其实是相对地址里的内容
- 其实就是数组名代表数组首地址,指针变量名本身代表指向数据的地址。
文章图片
分析代码四
文章图片
分析前面问题
总结
- 请问本题错在什么地方?为什么?
错在 printf(f.a->s).原因同代码三。
实际就是 数组名代表数组首地址,指针变量名代表指向数据的地址。
- f.a被初始化为空了嘛,用空指针访问成员变量为什么不crash(崩溃)?
- 编译器会隐形的将NULL转化为 结构体的首地址。
- 因此NULL指针可以访问成员变量时,但是只能访问成员的地址,一旦对空闲地址解引用,就会导致crash。
- 其实本篇是 数组名代表数组首元素导致,指针变量代表指向数据的地址。的另外一种解释。博主也是看完大佬陈皓文章后才发现的。大佬就是大佬!!!
推荐阅读
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 人生两件宝(好身体,好心情!)
- 【生信技能树】R语言练习题|【生信技能树】R语言练习题 - 中级
- 人如果没梦想,和咸鱼有什么区别(自媒体时代把握住就能咸鱼翻身)
- 一起来学习C语言的字符串转换函数
- C语言字符函数中的isalnum()和iscntrl()你都知道吗
- C语言浮点函数中的modf和fmod详解
- C语言中的时间函数clock()和time()你都了解吗
- 绘本讲师训练营【18期】14/21《我的情绪小怪兽》故事会新体验
- 一个健康的APP和健全的人格大体类似