C中的void类型

2024-03-08

The void从各种不同的情况来看,C 中的 type 似乎很奇怪。有时它的行为就像普通的对象类型,例如int or char,有时它毫无意义(正如它应该的那样)。

看看我的片段。首先,你可以这样做似乎很奇怪declare a void对象,意味着你什么也不声明。

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

如果任何其他类型的表达式被计算为 void 表达式,其值或指示符被丢弃。(ISO/IEC 9899:201x,6.3.2.2 无效)

我试图用一个来调用我的函数void演员,但我的编译器给了我(Clang 10.0):

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

So the void在原型中意味着nothing,而不是类型void.

但是后来,我创建了一个指向void,取消引用它,并分配“result” to my 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;
}

Is void一个实际的类型,或者一个没有任何意义的关键字?因为有时它的行为就像指令“这里不允许任何事情”,有时就像一个真实的类型。

EDIT: 这个问题是NOT重复的。这纯粹是关于语义的void类型。我不需要任何关于如何使用的解释void, 指向void或任何其他东西。我想要一个符合 C 标准的答案。


在C语言中voidtype 的引入比“null”或“nothing”更具有“不关心”的含义,并且它用于不同的范围。

The void关键字可以引用void type, a reference to void, a void expression, a void operand or a void function。它还显式定义了一个没有参数的函数。

让我们看一下其中的一些。


The void type

首先void对象存在并具有一些特殊属性,如中所述ISO/IEC 9899:2017,§6.2.5 类型:

  1. void 类型包含一组空值;它是一个不完整的对象类型,无法完成。

Pointers

越有用的reference to void, or void *,是对不完整类型的引用,但本身定义良好,然后是完整类型,具有大小,并且可以用作任何其他标准变量,如中所述ISO/IEC 9899:2017,§6.2.5 类型:

  1. 指向 void 的指针应具有与指向字符类型的指针相同的表示和对齐要求。

    类似地,指向兼容类型的限定或非限定版本的指针应具有相同的表示和对齐要求。

    所有指向结构类型的指针应具有相同的表示和对齐要求。

    所有指向联合类型的指针应具有相同的表示和对齐要求。

    指向其他类型的指针不需要具有相同的表示或对齐要求。


投射到void

它可以用作cast使表达式无效,但允许完成任何副作用这样的表达。该概念在以下标准中进行了解释:ISO/IEC 9899:2017,§6.3 转换,§6.3.2.2 无效:

  1. void 表达式(类型为 void 的表达式)的(不存在的)值不得以任何方式使用,并且隐式或显式转换(除 void 之外)不得应用于此类表达式。

    如果任何其他类型的表达式被计算为 void 表达式,则其值或指示符将被丢弃。 (评估 void 表达式的副作用。)

铸造的实际例子void它的用途是防止函数定义中未使用的参数发出警告:

int fn(int a, int b)
{
    (void)b;    //This will flag the parameter b as used 

    ...    //Your code is here

    return 0;
}

上面的代码片段显示了用于消除编译器警告的标准做法。演员阵容void参数的b充当不生成代码和标记的有效表达式b用于防止编译器抱怨。


void功能

这段落§6.3.2.2 无效该标准,还包括一些解释void函数,即不返回表达式中可用的任何值的函数,但无论如何都会调用函数来实现副作用。


void指针属性

正如我们之前所说,指向void更有用,因为它们允许以通用方式处理对象引用,因为它们的属性在ISO/IEC 9899:2017,§6.3.2.3 指针:

  1. 指向 void 的指针可以与指向任何对象类型的指针相互转换。

    指向任何对象类型的指针都可以转换为指向 void 的指针,然后再转换回来;结果应等于原始指针.

作为实际示例,想象一个函数根据输入参数返回指向不同对象的指针:

enum
{
    FAMILY,     //Software family as integer
    VERSION,    //Software version as float
    NAME        //Software release name as char string
} eRelease;

void *GetSoftwareInfo(eRelease par)
{
    static const int   iFamily  = 1;
    static const float fVersion = 2.0;
    static const *char szName   = "Rel2 Toaster";

    switch(par)
    {
        case FAMILY:
            return &iFamily;
        case VERSION:
            return &fVersion;
        case NAME:
            return szName;
    }
    return NULL;
}

在此代码片段中,您可以返回一个依赖于输入的通用指针par value.


void作为函数参数

指某东西的用途void函数定义中的参数是在所谓的 ANSI 标准之后引入的,以有效区分具有可变参数数量的函数和具有以下参数的函数:没有参数.

从标准ISO/IEC 9899:2017, 6.7.6.3 函数声明符(包括原型):

  1. 类型的未命名参数的特殊情况void因为列表中唯一的项目指定该函数没有参数。

实际编译器仍然支持带有空括号的函数声明以实现向后兼容性,但这是一个过时的功能,最终将在未来版本的标准中删除。看未来方向 - §6.11.6 函数声明符:

  1. 使用带有空括号的函数声明符(不是原型格式参数类型声明符)是一种过时的行为 特征。

考虑以下示例:

int foo();         //prototype of variable arguments function (backward compatibility)
int bar(void);     //prototype of no arguments function
int a = foo(2);    //Allowed
int b = foo();     //Allowed
int c = bar();     //Allowed
int d = bar(1);    //Error!

现在类似于您的测试,如果我们调用该函数bar如下:

int a = 1;
bar((void)a);

触发错误,因为转换为void对象不会将其置空。所以你仍在尝试通过void对象作为没有任何函数的参数。


副作用

根据要求,这是一个简短的解释副作用概念。

副作用是指从语句执行中派生的对象和值的任何更改,这不是直接预期的效果。

int a = 0;
(void)b = ++a;

在上面的代码片段中,void 表达式失去了直接效果,赋值b,但作为副作用增加的价值a.

标准中唯一解释含义的参考文献可以在5.1.2.3 程序执行:

  1. 访问易失性对象、修改对象、修改对象 文件,或调用执行任何这些操作的函数都是 副作用,即执行状态的变化 环境。

    表达式的求值一般包括两个值 副作用的计算和启动.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C中的void类型 的相关文章

随机推荐