【问题标题】:What is the purpose of (void)variable in C? [duplicate]C中(void)变量的目的是什么? [复制]
【发布时间】:2019-09-19 21:44:25
【问题描述】:

我正在阅读this book 并且我遇到了这段代码:

static void
task1(void *args) {
    int i;

    (void)args;

    for (;;) {
        gpio_toggle(GPIOC,GPIO13);
        for (i = 0; i < 1000000; i++)
            __asm__("nop");
    }
}

除了第 5 行外,我都(相对)了解。(void)args; 在做什么?

args 没有在函数体中使用,我知道如果不使用参数,那么可以写

static void
task2(void *args __attribute((unused))) {
     // code here
}

这里没有做。那么(void) 写成这样是做什么的呢?

【问题讨论】:

  • 奇怪的是,没有一个答案明确说明(void) 中的(void) args; 正在做什么。它是一个强制转换,类似于(int) 3.5,将3.5 转换为int,或(char *) &amp;x,将x 的地址转换为指向char 的指针。名义上,(void) args; 将args 的值转换为void 类型。由于void 没有值,因此转换不会产生任何值。在那之后,这里和原文的答案都适用:这是一种告诉编译器你故意忽略args的方式。

标签: c embedded


【解决方案1】:

一般来说,当不使用函数参数时,编译器可能会警告您。毕竟,如果您不打算使用它,为什么要首先将其放在那里?

实际上,这是对参数的人为使用,除了告诉编译器您知道自己在做什么之外没有任何用处,所以“Shatupalready with the warning!”

(void) args 适用于我见过的所有平台。我相信 __attribute((unused)) 是 gcc 特有的东西。

【讨论】:

    【解决方案2】:

    每个表达式都有一个类型。任何表达式都可以通过添加分号变成语句。如果 表达式语句 产生非void 值,则该值将被丢弃。

    编译器通常会警告某个值被丢弃。即使是像

    这样的简单案例
    printf("hello world\n");
    

    悄悄丢弃printf返回的int值;编译器警告可能会提醒程序员测试该值并在指示调用失败时采取一些措施。 (大多数编译器在这种特殊情况下不会发出警告,因为printf 调用通常在语句上下文中使用,结果被忽略。)

    将表达式转换为void 类型会丢弃结果,但它会明确这样做。这可能会使编译器警告静音。

    就语言而言,(void) 强制转换将结果转换为类型void,这相当于丢弃该结果。从程序员的角度来看,(void) 强制转换可以消除未使用值的警告,因为您明确忽略它并向编译器断言您知道自己在做什么(即使你不这样做)。

    引用 C 标准 (N1570 draft),6.3.2.2:

    void 表达式的(不存在的)值(具有 type void) 不得以任何方式使用,并且不得以任何方式隐含或 显式转换(void 除外)不适用于 这样的表达。如果任何其他类型的表达式被评估为 一个 void 表达式,它的值或指示符被丢弃。 (避免 表达式的副作用被评估。)

    和 6.2.5 第 19 段:

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

    【讨论】:

      【解决方案3】:

      这是一个编译器警告(-W unused-variable 或 -W all),他们通过使用它来抑制。你是对的,__attribute__((unused)) 是一个有效的 C 宏,可以满足你的要求,但这是一个偏好问题。并非所有 C 编译器都支持它。

      来源: http://www.keil.com/support/man/docs/armcc/armcc_chr1359124983230.htm https://en.cppreference.com/w/cpp/compiler_support

      【讨论】:

        【解决方案4】:

        void是一个空数据类型,它可以用于不同数量的情况。

        “返回”void 的函数不返回任何内容(根据定义,它是一个过程,而不是一个函数)。

        void*(void 的指针)通常用作通用指针(指向没有特定数据类型的内存地址的指针)。编译器将允许您将此指针分配给任何其他指针类型,而无需显式转换。

        例如,malloc() 返回void*,因此您可以执行int* v = malloc(sizeof(int)*10)); 之类的操作,而无需将malloc() 的返回值显式重铸为int*。

        反之亦然,以void* 作为参数的函数将采用任何指针类型而无需显式转换。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-05-09
          • 2014-02-20
          • 2017-02-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-06-28
          • 2018-05-05
          相关资源
          最近更新 更多