在C中取消引用指向数组的NULL指针是否有效? [英] Is dereferencing a NULL pointer to array valid in C?

查看:96
本文介绍了在C中取消引用指向数组的NULL指针是否有效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此行为是否已定义?

volatile long (*volatile ptr)[1] = (void*)NULL;
volatile long v = (long) *ptr;

printf("%ld\n", v);

之所以起作用,是因为通过取消指向数组的指针,我们正在接收数组本身,然后该数组衰减为指向其第一个元素的指针.

It works because by dereferencing pointer to array we are receiving an array itself, then that array decaying to pointer to it's first element.

更新的演示: https://ideone.com/DqFF6T

此外,GCC甚至将下一个代码视为常量表达式:

Also, GCC even considers next code as a constant expression:

volatile long (*ptr2)[1] = (void*)NULL;
enum { this_is_constant_in_gcc = ((void*)ptr2 == (void*)*ptr2) };
printf("%d\n", this_is_constant_in_gcc);

基本上,在编译时取消引用ptr2;

Basically, dereferencing ptr2 at compile time;

推荐答案

此:

long (*ptr)[1] = NULL;

正在声明一个指向"1 long 的数组"的指针(更确切地说,类型为 long int(*)[1] ),其初始值为的 NULL .一切正常,任何指针都可以为 NULL .

Is declaring a pointer to an "array of 1 long" (more precisely, the type is long int (*)[1]), with the initial value of NULL. Everything fine, any pointer can be NULL.

然后,这个:

long v = (long) *ptr;

正在取消引用 NULL 指针,该指针是 未定义行为 .所有的赌注都没有,如果您的程序没有崩溃,以下语句可能会打印任何值或确实执行其他任何操作.

Is dereferencing the NULL pointer, which is undefined behavior. All bets are off, if your program does not crash, the following statement could print any value or do anything else really.

让我再说清楚一次:未定义的行为意味着任何事情都会发生.没有解释为什么在调用未定义的行为后会发生什么奇怪的事情,也没有必要.编译器可以很好地发出16位实模式x86程序集,产生可以删除整个主文件夹的二进制文件,可以发出Apollo 11指导计算机程序集代码,或其他任何方式.这不是不是错误.完全符合标准.

Let me make this clear one more time: undefined behavior means that anything can happen. There is no explanation as to why anything strange happens after invoking undefined behavior, nor there needs to be. The compiler could very well emit 16-bit Real Mode x86 assembly, produce a binary that deletes your entire home folder, emit the Apollo 11 Guidance Computer assembly code, or whatever else. It is not a bug. It's perfectly conforming to the standard.

您的代码似乎起作用的唯一原因是因为GCC 完全出于巧合而决定执行以下操作( Godbolt链接):

The only reason your code seems to work is because GCC decides, purely out of coincidence, to do the following (Godbolt link):

mov     QWORD PTR [rbp-8], 0    ; put NULL on the stack
mov     rax, QWORD PTR [rbp-8]
mov     QWORD PTR [rbp-16], rax ; move NULL to the variable v

导致 NULL -取消引用从未真正发生.这很可能是取消引用 ptr ¯\ _(ツ)_/¯

Causing the NULL-dereference to never actually happen. This is most probably a consequence of the undefined behavior in dereferencing ptr ¯\_(ツ)_/¯

有趣的是,我之前在评论中说过:

Funnily enough, I previously said in a comment:

取消引用 NULL 无效,并且基本上总是会导致分段错误.

dereferencing NULL is invalid and will basically always cause a segmentation fault.

但是,当然,由于是未定义的行为,因此基本上总是"是错误的.我认为这是我第一次看到空指针取消引用不会导致SIGSEGV.

But of course, since it is undefined behavior that "basically always" is wrong. I think this is the first time I ever see a null-pointer dereference not cause a SIGSEGV.

这篇关于在C中取消引用指向数组的NULL指针是否有效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆