指向0x0位置的指针与设置为NULL的指针有什么区别?


12

指向0x0000的指针是否与设置为NULL的指针相同?如果用C语言定义了NULL值,那么它将物理地转换到什么位置?是否与0x0000相同?在哪里可以找到有关这些概念的更多详细信息?


1
这已经被问过堆栈溢出- stackoverflow.com/questions/1296843/...。我认为这对我们来说是一个临界点,但是我愿意暂时将其从怀疑中受益。
克里斯·弗雷德

Answers:


12

这里的大多数答案都没有解决(至少没有明确指出)的一点是,空指针是在执行期间存在的值,而空指针常量是C源代码中存在的语法构造。

空指针常量,如卡尔森的答案正确地指出,或者是一个整数常量表达式用值0(一个简单的0是最常见的例子),或这样的表达浇铸到void*(如(void*)0)。

NULL是一个宏,在<stddef.h>和其他几个标准头中定义,它扩展为实现定义的null指针常量。扩展通常为0((void*)0)(需要用括号括起来才能满足其他语言规则)。

因此0,当在需要指针类型表达式的上下文中使用文字时,字面量始终求值为null pointer,即唯一指针值,该指针值指向任何对象。但这并不意味着有关的任何表示空指针。空指针通常表示为全零位,但是它们可以表示为任何东西。但是,即使一个空指针表示为0xDEADBEEF0(void*)0仍是一个空指针常量

这个答案对计算器的问题涵盖了这口井。

这意味着,除其他事项外,memset()或者calloc(),它可以设置内存的所有位归零区域,不一定会设置在该区域中任何指向空指针。他们可能会在大多数实现中这样做,但是语言并不能保证做到这一点。

我不知道为什么这个问题是没有考虑重复这一块,或者它是如何的外用这里。


1
我对C的设计和发展感到不满意的地方之一是,数字零继续被用作空指针的不赞成使用的表示形式。早在该语言的早期(例如,在函数原型之类的东西问世之前),指针和整数就可以互换,以至于对空指针使用“ 0”很简单,并且可以“正常工作”。但是,一旦有必要在整数数量零和空指针之间进行区分,就应该弃用“ 0”表示法,而推荐使用关键字或运算符序列。
超级猫

这是否意味着根据平台将NULL指针分配为NULL时,它实际上可能指向某个位置?空指针常量可能是一种语法构造,但是当代码运行时究竟会发生什么?让我们假设此语法结构已在GNU / Linux平台上进行了编译。当我们给它赋NULL时,指针值是什么?此地址与其他任何地址有何不同?
2012年

1
@Arpith:给指针对象赋值NULL或任何null指针常量,都会将该对象的值设置为null指针。在机器级别,它很可能指向一些有效的内存块。取消引用空指针具有未定义的行为;在地址处访问大块内存0x0000000是有效的行为,正如其他任何事情一样。该地址与任何其他地址的不同之处在于(a)比较等于NULL,以及(b)比较不等于指向C对象的任何指针。空指针是一个任意指针值,用于指示它没有指向任何东西。
基思·汤普森

1
在机器级别,它可能指向一些有效的内存块,但是在大多数 C环境中,它将指向无效的内存,因此任何使用指针的尝试都将导致硬件陷阱/故障/异常。它通常仅在最简单的硬件平台(不支持内存管理的平台)上使用,其中NULL指针指向有效的内存位置。
所罗门慢

7

每个平台都可以随意定义NULL。

根据C标准,如果为指针分配零,则它将转换为NULL值(针对该平台。)但是,如果采用NULL指针并将其强制转换为int,则不能保证将得到零。在每个平台上。但是事实是,在大多数平台上,它将为零。

有关这些内容的信息,请参见《 C语言规范》。我无法保证其可靠性的一个来源是:http : //www.winapi.co.kr/pds/doc/ISO-C-FDIS.1999-04.pdf


2
如果他们选择脱离标准,他们可以自由地重新定义NULL pointer constant。据我所知,没有编译器可以做到这一点。
Karlson 2012年

有没有没有将NULL实现为0的编译器?并且NULL是否保证评估为false?
ugoren 2012年

根据标准,NULL保证评估为false。我不知道是否有没有将NULL实现为0的编译器(实际上是平台),我对此表示严重怀疑,但该标准并未禁止它,所以谁知道。
Mike Nakis 2012年

内存中抽象的“空指针常量”(如规范中所述)的表示(这可能是平台制造商所喜欢的)与NULL宏的定义(必须0在C ++和C 0(void *)0C中扩展为)之间存在混淆,因为那是真正的“空指针常量”。
Jan Hudec 2012年

尽管从理论上可以将NULL定义为任何值,但是该标准保证了将类型0强制转换为指针的int常量将产生空指针(ISO 9899:1999 6.3.2.3/3)。stddef.h的NULL宏必须是一个空指针(7.17 / 3),因此,编译器不将NULL实现为0或(void *)0会非常麻烦。


0

根据C标准文档部分6.3.2.3

一个值为0的整数常量表达式,或将这种类型强制转换为void *类型的表达式称为空指针常量。55)如果将空指针常量转换为指针类型,则得到的指针称为空指针。保证比较不等于指向任何对象或函数的指针。

到目前为止,我还没有看到可以摆脱这种情况的编译器。


@PéterTörök你是对的,这是一个错误。:)
Karlson 2012年

1
是的,但是请注意,它没有说出实际上具有数值0的指针的任何内容。尽管在大多数平台上,它可能没有。
Jan Hudec 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.