【问题标题】:Can a null pointer constant be any integer constant expression evaluated to 0?空指针常量可以是任何计算为 0 的整数常量表达式吗?
【发布时间】:2020-05-11 16:45:02
【问题描述】:

标准说:

“值为 0 的整型常量表达式,或这种类型转换为 void* 的表达式,称为 空指针常量。67) 如果为空指针常量转换为指针类型,生成的指针,称为 空指针,保证与指向任何对象或函数的指针不相等。"


"67) 宏 NULL 在 stddef.h(和其他头文件)中定义为空指针常量;参见 7.19。"

来源:ISO/IEC 9899:2018 (C18),§6.2.3.2/3“指针”。

最常见的空指针常量当然是0(void*) 0被大多数实现用作空指针常量,但作为标准要求 - "值为 0 的整型常量表达式,或转换为 void* 类型的表达式 - 空指针常量 也应该是任何以下内容:

  1. 1 * 0
  2. 0 * 0
  3. 0 - 0
  4. 25 - 25
  5. (-4) + (4)
  6. (0 * ((0 * 25) * 3)
  7. (0) * (-100)

就像他们的任何以(void*) 开头的吊坠一样,f.e. (void*) (1 * 0)(void*) (25 - 25)

以及布尔表达式:

  1. (void*) ((1 + 1) == 25)
  2. (void*) !(9)

因此,任何类似以下之一的陈述:

  1. int* ptr = 25 - 25;
  2. int* ptr = (void*) ((-4) + 4);
  3. int* ptr = (0 * ((0 * 25) * 3);
  4. int* ptr = (void*) !(9);
  5. int* ptr = ((1 + 1) == 25);

应根据标准将ptr 设为空指针


  • 我的担忧是对的还是有什么问题?

我正在寻找 C 标准中任何使本文无效的部分。

据我搜索,Stack Overflow 上不应该有此问题的重复项。

【问题讨论】:

  • 我不确定25 - 25 是常量的标准保证。
  • @EugeneSh。不是整数常量表达式吗?
  • 我不明白为什么这些不起作用。请注意,您的问题 title(“Can ... 任何计算为 0 的表达式”)是不同的,并且 not 为真。例如,(void*) strlen("") 不能保证为空指针。
  • port70.net/~nsz/c/c11/n1570.html#6.6 - 似乎列出了必要条件,但不是充分条件。所以我不确定一个表达式可以保证是不变的。

标签: c pointers null language-lawyer constant-expression


【解决方案1】:

你是对的,所有这些都是有效的。

C standard 第 6.6 节规定:

1

constant-expression:
    conditional-expression

...

3 常量表达式不应包含赋值、递增、递减、函数调用或逗号运算符,除非它们包含在未计算的子表达式中。

...

6一个整数常量表达式应该是整数类型并且 只能有整数常量的操作数,
枚举常量、字符常量、sizeof 表达式 其结果是整数常量、_Alignof 表达式和 作为强制转换的直接操作数的浮动常量。投掷 整数常量表达式中的运算符只能转换 算术类型转换为整数类型,除了作为 sizeof_Alignof 运算符的操作数。

您示例中的每个表达式都符合此描述,即:

  • 所有操作数都是整数常量
  • 表达式是一个条件表达式(即不使用赋值或逗号运算符),没有递增、递减或函数调用运算符
  • 评估为 0

所以所有都是将NULL分配给指针的有效方法。

一些整数常量表达式的例子:

int x = 1;
int *ptr1 = (3, 0);    //  invalid, comma operator not allowed
int *ptr2 = (x = 0);   //  invalid, assignment not allowed
int *ptr3 = x - 1;     //  invalid, an operand is not an integer constant

【讨论】:

    【解决方案2】:

    是的。

    [C99 6.6/6]: 整数常量表达式应具有整数类型,并且应仅具有整数常量、枚举常量、字符常量、结果为整数常量的 sizeof 表达式和作为强制转换的直接操作数的浮点常量的操作数。整数常量表达式中的强制转换运算符只能将算术类型转换为整数类型,除非作为 sizeof 运算符的操作数的一部分。

    请注意,在 C++ 中情况并非如此,空指针常量的定义不同:

    [conv.ptr]/1: 空指针常量是一个整数文字 ([lex.icon]),其值为 0 或 std​::​nullptr_­t 类型的 prvalue[..]

    【讨论】:

    • 应该说明结论
    • @EugeneSh。结论在第一行。
    猜你喜欢
    • 2014-12-16
    • 2016-04-03
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 2016-03-01
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多