【发布时间】:2020-05-04 12:38:17
【问题描述】:
这种行为是否已定义?
volatile long (*volatile ptr)[1] = (void*)NULL;
volatile long v = (long) *ptr;
printf("%ld\n", v);
它之所以有效,是因为通过取消引用指向数组的指针,我们接收到一个数组本身,然后该数组衰减为指向它的第一个元素的指针。
更新的演示:https://ideone.com/DqFF6T
此外,GCC 甚至将下一个代码视为常量表达式:
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;
【问题讨论】:
-
你的问题很不清楚...取消引用NULL是无效的,基本上总是会导致分段错误。
-
是的,确实发生了取消引用。
ptr是一个指针。 -
因为“工作”是未定义行为的绝佳且完全有效的示例。未定义的行为 not 是否意味着“它不起作用”。这意味着它可能会起作用。它可能会失败。 未定义会发生什么。
-
最后关于为什么应该定义行为的论点实际上使这个问题变得有点有趣。
-
因为指向数组的指针和指向其他东西的指针是不同的东西。 - 从技术上讲,它们不是。指针指向某种类型的对象的地址,不管这个对象是否是数组的一部分。它可能有一些实现定义的原因来选择另一个,但每个标准没有区别。 当解引用指向数组的指针时,我们会收到一个数组本身。 不,当你解引用指向数组的指针时,实际上你访问的是该数组的第一个元素对象,根据我上面所说的。
标签: c arrays pointers null dereference