c - C 中的 void 类型

标签 c language-lawyer standards semantics void

C 中的void 类型从各种不同的情况来看似乎很奇怪。有时它的行为就像一个普通的对象类型,例如 intchar,有时它只是没有任何意义(它应该如此)。

看看我的代码片段。首先,您可以声明一个void对象,这意味着您什么都不声明,这似乎很奇怪。

然后我创建了一个 int 变量并将其结果转换为 void,然后丢弃它:

If an expression of any other type is evaluated as a void expression, its value or designator is discarded. (ISO/IEC 9899:201x, 6.3.2.2 void)

我试图用 void 转换调用我的函数,但我的编译器给了我 (Clang 10.0):

error: too many arguments to function call, expected 0, have 1

因此原型(prototype)中的 void 表示,而不是 void 类型。

但随后,我创建了一个指向 void 的指针,取消引用它,并将“result”分配给我的 int 变量。我收到“不兼容类型”错误。 这意味着 void 类型确实存在于此处。

extern void a; // Why is this authorised ???

void foo(void); // This function takes no argument. Not the 'void' type.

int main(void)
{
    int a = 42;
    void *p;

    // Expression result casted to 'void' which discards it (per the C standard).
    (void)a;

    // Casting to 'void' should make the argument inexistant too...
    foo((void)a);

    // Assigning to 'int' from incompatible type 'void': so the 'void' type does exists...
    a = *p;

    // Am I not passing the 'void' type ?
    foo(*p);

    return 0;
}

void 是一个实际类型,还是一个没有任何意义的关键字?因为有时它的行为类似于指令“此处不允许任何内容”,有时又类似于实际类型。

编辑:这个问题不是重复。它纯粹是关于 void 类型的语义。我不想解释如何使用 void、指向 void 的指针或任何其他内容。我想要一个符合 C 标准的答案。

最佳答案

void 是一种类型。根据 C 2018 6.2.5 19,该类型没有值(它可以表示的值集为空),它是不完整的(它的大小未知),它不能完成(它的大小未知)。

关于extern void a;,this没有定义对象。它声明一个标识符。如果在表达式中使用 a(作为 sizeof_Alignof 运算符的一部分除外),则必须在某处为其定义在程序中。由于在严格符合 C 中不能定义 void 对象,因此不能在表达式中使用 a。所以我认为这个声明在严格符合 C 中是允许的,但没有用。它可能在 C 实现中用作扩展,允许获取类型未知的对象的地址。 (例如,在一个模块中定义一个实际对象 a,然后在另一个模块中将其声明为 extern void a; 并在那里使用 &a获取它的地址。)

(void) 作为参数列表的函数声明是一种困惑。理想情况下,() 可用于指示函数不带参数,如 C++ 中的情况。然而,由于 C 的历史,() 被用来表示未指定的参数列表,因此必须发明其他东西来表示没有参数。所以 (void) 被采用了。因此,(void) 是规则的一个异常(exception),即 (int) 是针对采用 int 的函数,( double) 用于函数采用 double ,依此类推—(void) 是一种特殊情况,意味着函数不采用参数,而不是采用 void.

foo((void) a) 中,转换不会使值“不存在”。它将 a 转换为 void 类型。结果是 void 类型的表达式。该表达式“存在”,但它没有值并且不能在表达式中使用,因此在 foo((void) a) 中使用它会导致错误消息。

关于c - C 中的 void 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53970709/

相关文章:

c - 关于 sizeof(char *) 和 sizeof(char[])

JavaScript 名称与 ID

c++ - 实现 is_constexpr_copiable

c++ - std::set 具有相同键和不同比较器的迭代器

C++ 重载解析不明确 - GCC

c - C 中的默认参数和参数提升

C、MPI : Program not terminating and not printing numbers

c - malloc 相对于 calloc 的安全/性能影响?

python - 关于如何使用 SWIG 为 python 做 c 包装的疑问

c - 如何在 C 中将 uint 转换为 int 且结果范围损失最小