问题1:
main函数里面的指针什么时候为NULL?
问题2:
自定义函数或在全局里面的指针什么时候为NULL?
问题3:
指针大小是怎么判断的?
问题4:
结构体内的指针在什么情况下为NULL?
——————————————————————————————
//指向结构体的指针Bitree *t
typedef struct Nd{
int data;
struct Nd *left;
struct Nd *right;
}Bst;
PS:指针大小由操作系统决定,32位系统4个字节,64位8个字节
本次实验为32位gcc编译器————————————————————
在main函数中,
Bst *a;
//表示指向一个Bst结构的指针,指针大小为4个字节
//也就是sizeof(a) = 4;sizeof(*a)=12;sizeof(&a)=4
注意:sizeof()的值是编译器给的,而printf(“%p”),是操作系统给的地址值,所以64位的win7下打印的变量地址还是64位二进制,不受32位编译器影响
//在main函数里面的指针
int main(){
Bst *a;
return 0;}
如果进行if(a){ printf("a不是空树!")}
那么,a还是会输出这个printf,因为a是野指针,如下图依次输出
&a
a
*a
野指针就是随机数,可见a指向的地址是00000002
反之,如果Bst *a=(Bst*)malloc(sizeof(Bst));
再判断也会输出a不是空树
||同理,对于main里面p,a,b,c,那一个为NULL?
typedef struct nod{
int data;
struct nod *l;
struct nod *r;
}BinaryT;
int main () {
BinaryT *p=0;||这里p等于'\0',NULL都行
BinaryT *a;
BinaryT *b=(BinaryT*)malloc(sizeof(BinaryT));
BinaryT c[2];
实际上,a是个随机数,不确定为不为0,(本次输出a的地址为00000039,若按整型输出则是3*16+9=57)
故a不为空,b,c均不为空。
作为对比,在自定义函数的情形指针的情况
————————————————
经过测试。。。。。。。
与在main函数情形一致
————————————————————————————————————————————————————————————————————
在全局的情况,全局变量和局部变量的在编译时的不同的处理方式,在程序编译的时候全局变量必须用常量进行初始化,也就是说直接在全局变量的内存地址直接存储变量的值;对于局部变量则在编译的时候不需要这样,编译的时候只需要将局部变量的赋值语句编译成机器代码,在程序运行到这里是在进行局部变量的赋值。
若用g++编译器对该程序进行编译,再碰到这里时,编译器会先把全局变量保存到.bss段中,而且默认值为0,但是会在main函数之前添加一条赋值语句,也就是相当于局部变量进行处理了。
Bitree *a;
||a会直接初始化为0
int main(){
if(a==NULL){
printf("a=NULL");
}
}
但是!!! a指向的内存为NULL了,那么结构体a内的指针是不可访问的,强行访问会运行时出错。
最后通牒!!!
在结构体内指针什么时候为NULL?
1——在main里面
情形一:野指针
int main(){
Bitree *a;
if(a->left==NULL){
printf("NULL");
}
}
结果:想都不用想,运行时报错!!!
一个随机数当地址,再用这个随机地址去找left和right,简直瞎搞
——————————————————————————————————————————————————
情形2: 分配内存情形
int main(){
Bitree *a=(Bitree*)malloc(sizeof(Bitree));
if(a->left==NULL){
printf("NULL");
}
}
运用类比法,相当于在main里面又定义了两个野指针,一个叫a->left,一个叫a->right。因此main里的结构体内指针不为空;
2——在自定义函数或全局情形
void isempty(){
Bitree *a;
if(a->left==NULL){
pritnf("null");
}
}
结果——类似与main函数,照样运行时报错!!!
若已分配内存(Bitree *a=(Bitree*)malloc(sizeof(Bitree));),则有
a->left和a->right照样是野指针,不为空
————————————————————————————————————————————————————————————————
全局的情形:
case 1
Bitree *a;
访问a,a是等于NULL的,但如果访问a->left,就是对野指针访问,会运行报错!!!
case 2
Bitree a;
Bitree b[2];
int main(){
if(a->left==NULL){
输出NULL
}
if(&b[0]->left==NULL){
输出NULL
}
}
注意:这两个都是NULL,因为类比如在全局定义了这两个指针,都会自动初始化
总结:访问指针的时候虚拟地址就会向物理地址映射,此时页表会去查看这块地址,而这块地址被存放在只读区,当页表发现地址是无效的,就会反映给操作系统,操作系统就会发送11号信号终止此进程,所以进程异常终止程序崩溃——————————————————————————每次定义一个指针要记得初始化为NULL,否则当做已分配了内存的指针使用!!!
转载:https://blog.csdn.net/weixin_42557786/article/details/102485899
查看评论