是((无效*)0)空指针常量? [英] Is ((void*)0) a null pointer constant?

查看:108
本文介绍了是((无效*)0)空指针常量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读这篇博客并根据部分的空指针常量和括号的前pressions 作者引用第6.3.2.3和ISO C标准6.5.1§说:

I'm reading this blog post and under the section Null pointer constants and parenthesized expressions the author references § 6.3.2.3 and § 6.5.1 from the ISO C standard and says:

它的的说,一个括号空指针常量是一个空指针常量。

It doesn't say that a parenthesized null pointer constant is a null pointer constant.

这意味着,严格来说,是(无效*)0 是一个空指针
  不变的,但((无效*)0)不是

Which implies, strictly speaking, that (void*)0 is a null pointer constant, but ((void*)0) is not.

然后:

我敢肯定,大多数C实现根本治疗括号空指针常数作为空指针常量,并定义 NULL 无论是作为 0 ((无效*)0),或以其他的方式。

I'm sure that most C implementations do treat a parenthesized null pointer constant as a null pointer constant, and define NULL either as 0, ((void*)0), or in some other manner.

这两个相关章节说:

第6.3.2.3

这是整型常量前pression值为0,或者这样的前pression
  转换为类型为void *,被称为空指针常量。

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.

第6.5.1

一个括号的前pression是主前pression。 它的类型和值
  那些相同的前加括号的pression的。
这是一个
  左值,函数标志或无效前pression如果
  前加括号的pression是,分别为左值,函数
  标志或无效前pression。

A parenthesized expression is a primary expression. Its type and value are identical to those of the unparenthesized expression. It is an lvalue, a function designator, or a void expression if the unparenthesized expression is, respectively, an lvalue, a function designator, or a void expression.

不粗体的一句顶撞提交人提出的((无效*)0)不是一个空指针常量?

Doesn't the bolded sentence contradict the author's claim that ((void*)0) is not a null pointer constant?

推荐答案

没有,没有。 (我承认是有点偏,因为引用的博客是我的。)

No, it doesn't. (I confess to being a bit biased, since the referenced blog is mine.)

粗体句话说,它的键入的和的的那些相同的前加括号的pression的。这是不够的,意味着它是一个空指针常量。

The bolded sentence says that its type and value are identical to those of the unparenthesized expression. That's not enough to imply that it's a null pointer constant.

考虑:

void *var = 0;

(无效*)0 是一个空指针常数。 ((无效*)0)具有相同的类型和值(无效*)0 VAR 的具有相同类型和值(无效*)0 ,而 VAR 显然不是一个空指针常量。

(void*)0 is a null pointer constant. ((void*)0) has the same type and value as (void*)0. var also has the same type and value as (void*)0, but var clearly is not a null pointer constant.

说了这么多,我99 +%确认的意图的是((无效*)0)是一个空指针常数,更普遍的,任何括号空指针常量是一个空指针常量。该标准的作者只是被忽视这么说。而且,由于前括号的pressions的描述6.5.1p5专门列举了被括号括前pressions继承了其他几个特点:

Having said that, I'm 99+% sure that the intent is that ((void*)0) is a null pointer constant, and more generally that any parenthesized null pointer constant is a null pointer constant. The authors of the standard merely neglected to say so. And since the description of parenthesized expressions in 6.5.1p5 specifically enumerates several other characteristics that are inherited by parenthesized expressions:

一个括号的前pression是主前pression。它的类型和值
  的那些相同的加括号的前pression的。它是一个
  左值,函数标志或无效前pression如果
  前加括号的pression是,分别为左值,函数
  标志或无效前pression。

A parenthesized expression is a primary expression. Its type and value are identical to those of the unparenthesized expression. It is an lvalue, a function designator, or a void expression if the unparenthesized expression is, respectively, an lvalue, a function designator, or a void expression.

遗漏令人担忧(但仅轻度左右)。

the omission is troubling (but only mildly so).

但是让我们假设,参数的缘故,即((无效*)0)不是一个空指针常量。这有什么区别呢?

But let's assume, for the sake of argument, that ((void*)0) is not a null pointer constant. What difference does it make?

(无效*)0 是一个空指针常数,它的值是一个类型的空指针无效* ,因此通过括号中的前pressions的语义((无效*)0)也有一个值,该值类型的空指针无效* 。无论(无效*)0 ((无效*)0)地址常量的。 (好吧,我的认为的他们。)那么什么情况下需要的空指针常量的和不接受的地址常量的?只有几

(void*)0 is a null pointer constant, whose value is a null pointer of type void*, so by the semantics of parenthesized expressions ((void*)0) also has a value that is a null pointer of type void*. Both (void*)0 and ((void*)0) are address constants. (Well, I think they are.) So what contexts require a null pointer constant and do not accept an address constant? There are only a few.

函数指针类型的前pression可以为平等空指针常量进行比较。 (对象指针可以进行​​比较,以键入无效* 的前pression,但一个函数指针可能没有,除非它是一个空指针常量)。所以这一点:

An expression of function pointer type may be compared for equality to a null pointer constant. (An object pointer may be compared to an expression of type void*, but a function pointer may not, unless it's a null pointer constant.) So this:

void func(void);
if (func == ((void*)0)) { /* ... */ }

将是一个约束冲突。

would be a constraint violation.

在一个赋值,一个空指针常数可以被分配给指针到功能类型的对象,并且将被隐式转换。类型的前pression 无效* 这不是一个空指针常量不能分配给一个函数指针。同样的限制适用于参数传递和初始化。因此,这:

In an assignment, a null pointer constant may be assigned to an object of pointer-to-function type, and will be implicitly converted. An expression of type void* that's not a null pointer constant may not be assigned to a function pointer. The same constraints apply to argument passing and initialization. So this:

void (*fp)(void) = ((void*)0);

将是一个违反约束,如果((无效*)0)不是一个空指针常量。由于评论者HVD找到这个。

would be a constraint violation if ((void*)0) were not a null pointer constant. Thanks to commenter hvd for finding this.

NULL 扩展为实现定义的空指针常量。如果((无效*)0)不是一个空指针常数,那么这样的:

The macro NULL expands to "an implementation-defined null pointer constant". If ((void*)0) is not a null pointer constant, then this:

#define NULL ((void*)0)

将是无效的。这将是强加的实施,而不是在编程的限制。需要注意的是这样的:

would be invalid. This would be a restriction imposed on the implementation, not on programmers. Note that this:

#define NULL (void*)0

肯定是无效的,因为在标准头的宏定义必须用括号充分保护在必要时(7.1.2p5)。如果没有括号,有效的前pression 的sizeof NULL 将是一个语法错误,扩展到的sizeof(无效*)后跟一个外来恒 0

is definitely invalid, since macro definitions in standard headers must be fully protected by parentheses where necessary (7.1.2p5). Without the parentheses, the valid expression sizeof NULL would be a syntax error, expanding to sizeof (void*) followed by an extraneous constant 0.

这篇关于是((无效*)0)空指针常量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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