C语言中的void语句是什么作用?

4
在C语言中,将void;放在一行上的作用是什么?编译器会发出警告,但我不明白它的意义。能够像这样在一行上放置void有什么意义吗?
#include <stdio.h>

int main() {
        void;
        printf("word dude");
        return 1;
}

eh

$ gcc -pedantic -ansi -Wall -Wextra eh.c -o eh
eh.c: In function 'main':
eh.c:4:2: warning: useless type name in empty declaration
$ ./eh
word dude

人们似乎对我的问题感到困惑:这行代码是什么意思?它有什么作用?为什么它是有效的?
void;

去掉无用的强制类型转换,因为这会引起不必要的讨论。


1
编译器告诉你你所做的是无用的。那么问题是什么? - Oliver Charlesworth
5
为什么这不是语法错误是一个真正的问题? - Kijewski
2
@Oil:问题是为什么这个可以编译,以及它的含义是什么。 - megazord
@megazord 请看我的回答,这不是C语言。你的编译器很好心地接受了它,但并没有义务这样做。例如,clang拒绝翻译这个程序。 - ouah
它能编译通过是因为编译器没有强制执行严格的符合性。它接受空声明,但会发出警告。要获得编译错误,请使用“-pedantic-errors”或通常使用“-Wall -Wextra -Werror”。 - Daniel Fischer
6个回答

2
      void;                       // 1
      (void)printf("word dude");  // 2

第一句话是无效的语句:这不是C语言。
在第二个语句中,(void)强制转换可以使你的意图清晰地丢弃返回值。另一个常见用途是使一些静态分析工具如Lint保持安静。

2

这个问题让我很感兴趣,因为我的第一个想法是K&R。我回到了我的旧K&R书(附录A p.192)上,找到了有关声明的简介(转录):

8.声明

声明用于指定C语言对每个标识符的解释方式;它们不一定保留与标识符相关联的存储空间。声明的形式为
    declaration:
        decl-specifier declarator-listopt;

声明列表中的declarators包含正在声明的标识符。decl-specifiers由类型和存储类别说明符的序列组成。
    decl-specifiers:
        type-specifier decl-specifiersopt
        sc-specifier decl-specifiersopt

这使我相信,delarator列表是可选的(意味着它可以为空)。

在下一页混淆的情况下,它列出了合法的type-specifier值集合,而void并不是其中之一。

在我的狭义解释中,这仍然可能是合法的(但已过时的)C语言。


这个问题还没有得到回答。 - Thomas
在我看來,這並沒有明確的答案。很長一段時間以來,K&R書籍是參考手冊,直到ANSI C標準化出現。ANSI C是K&R的超集,因此K&R的很多怪異之處都被繼承了。儘管它可能不完整,但我認為對於“為什麼這是有效的”這個問題的最佳答案是“因為K&R這樣說”。 - Ralph Allan Rice
我在谷歌搜索后来到这里,是为了回应在 GitHub 存储库中发现一些奇怪的行(https://github.com/libfuse/libfuse/blob/96ad05c8e12bae3c53401d4a856c168ef6c04345/example/hello.c#L87)。不太确定存储库试图实现什么。也许与防止编译器优化未使用的参数有关? - unsynchronized

1
void;

这样做毫无意义,它没有任何作用。

你是从书上看来的吗?一定是个错误。

稍微跑题了一下,如果返回值是0通常表示程序正常结束,任何其他值都表���出现问题(按照惯例)

更新:

看起来你又加了一行:

(void)printf("word dude");

这个 - 与之前的 void; 不同 - 明确告诉编译器忽略 printf() 函数的返回值(打印的字符数),并防止警告消息,以避免编译器或其他工具(如 lint)在挑剔/迂腐设置下发出投诉。

通常情况下,您不会看到经常使用的函数出现这种情况,但对于其他函数可能会出现。


4
我知道,我之所以打了1是因为我正在吃东西,这样更容易按到。 - megazord
@megazord 哈哈.. 最好的理由 :).. 而且它并不会影响这个例子。 - Levon
@megazord,我看到你添加了另一行代码 void printf(..) .. 我更新了我的答案以包含它。 - Levon

0

看起来像是旧式的函数参数声明方式。这相当于int main(void)。一些编译器仍然接受它,而一些则不接受。例如,我尝试了两个编译器,这段代码在这两个编译器中都可以编译:

void main(i, j) {
    int;
    long;

    i = 12;
    j = 123456;
    printf("%d %d\n", i, j);
}

在C函数声明中使用未类型化的参数的答案对于这种情况有更精确的定义。

无论如何,这并不是推荐的做法,所以我们能否坚持“正常”的函数声明方式呢? :)


1
你展示的不是我所知道的K&R风格。在K&R风格中,类型在开括号之前与它们的名称一起声明。这里它们在函数内部定义,但没有名字。这是另一种定义风格吗?还是'i,j'默认为'int',而'int;long;'被忽略了? - ugoren

0

如果你将 void 改为 int 或其他任何类型,它会打印相同的错误信息。

void 是一种类型,它期望在该类型后面跟着某些内容。如果只写了 int 而没有变量(或函数)名称,那么这根本没有意义。


0

void在C语言中被用作数据类型,如果考虑一下的话,我从来没有听说过在C语言中等效于NOP的汇编语言,所以只有void自身出现在一行上可能是一个错误。


1
我不是在问void是什么,我是在问如果只有一行代码写着"void;",它代表什么意思。 - megazord

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接