c99中的func()vs func(void) [英] func() vs func(void) in c99

查看:60
本文介绍了c99中的func()vs func(void)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

void func()
实际上,空参数表示可以接受任何参数。

void func() In practice, an empty parameter means any argument is accepted.

void func(void)不接受任何参数。

但是在标准C99中,我发现这样的行:

But in Standard C99, I find such lines:


6.7.5.3函数声明符(包括原型)

14标识符列表仅声明函数参数的标识符。 作为该函数定义的一部分的函数声明器中的空白列表表示该函数没有参数。不属于该函数定义的一部分的函数声明器中的空白列表表示

6.7.5.3 Function declarators (including prototypes)
14 An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.

根据标准 func() func(void)是相同的吗?

according to the standard, func() and func(void) is the same?

推荐答案

TL; DR



在声明中,

TL;DR

In declarations,

void func1();     // obsolescent
void func2(void);

行为是完全不同的。第一个声明一个没有任何原型的函数-它可能需要任何数量的参数!后者用原型声明了一个函数,该函数没有参数并且不接受任何参数。

the behaviour is quite different. The first one declares a function without any prototype - and it may take any number of arguments! Whereas the latter declares a function with a prototype, that has no parameters and accepts no arguments.

definitions

void func1() { }     // obsolescent

void func2(void) { }




  • 前者声明并定义了一个函数 func1 参数和没有原型

    后者声明并定义了函数 func2 具有没有参数的原型

    The latter declares and defines a function func2 with a prototype that has no parameters.

    这两个行为明显不同,而C编译器必须在调用带有错误数量的参数的原型函数时打印诊断消息,而在没有原型的函数时不需要这样做。

    These two behave distinctly in that whereas the C compiler must print a diagnostic message when calling a prototyped function with wrong number of arguments, it needn't do so when calling a function without prototype.

    即,鉴于以上定义

    func1(1, 2, 3); // need not produce a diagnostic message
    func2(1, 2, 3); // must always produce a diagnostic message 
                    // as it is a constraint violation
    

    在严格符合标准的程序中,调用都是非法的,因为根据 6.5.2.2p6

    However both calls are illegal in strictly-conforming programs as they're explicitly undefined behaviour as per 6.5.2.2p6.

    此外,空括号被认为是过时的功能:

    Furthermore, the empty parentheses are considered an obsolescent feature:


    使用带空括号的函数声明符(不是原型格式的参数类型声明符)是过时的功能。

    The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.


    使用带有单独的参数标识符和声明列表的函数定义(不是原型)格式参数类型和标识符声明符)是过时的功能。

    The use of function definitions with separate parameter identifier and declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature.



    详细信息



    有2个相关但截然不同的概念:参数和arg ments。

    In detail

    There are 2 related, yet distinct concepts: parameters and arguments.


    • 参数是传递给函数的值。

    • arguments are the values passed into the function.

    参数是函数中的名称/变量,在输入函数时设置为参数值

    parameters are the names/variables within the function that are set to the values of the arguments when the function entered

    在以下摘录中:

    int foo(int n, char c) {
        ...
    }
    
    ...
    
        foo(42, ch);
    

    n c 是参数。 42 ch 是自变量。

    n and c are parameters. 42 and ch are arguments.

    引用的摘录仅涉及函数的参数,但不涉及函数的原型或参数。

    The quoted excerpt only concerns the parameters of a function, but doesn't mention anything about the prototype or arguments to the function.

    声明 void func1()表示函数 func1 可以用调用任何数量的 arguments ,即未指定有关参数数量的信息(作为单独的声明,C99将其指定为没有参数指定的函数),而声明<$ c $ c> void func2(void)表示函数 func2 根本不接受任何参数

    The declaration void func1() means that the function func1 can be called with any number of arguments, i.e. no information about the number of arguments is specified (as a separate declaration, C99 specifies this as "function with no parameter specification), whereas the declaration void func2(void) means that the function func2 does not accept any arguments at all.

    问题中的引号表示在函数定义中, void func1() void func2(void)都表示没有参数,即设置为参数值的变量名称输入功能时。 void func(){} void func()形成鲜明对比; 前者声明 func 确实没有任何参数,而后者是函数 func 的声明,而 都不是参数

    The quote in your question means that within a function definition, void func1() and void func2(void) both signal them that there are no parameters, i.e. variable names that are set to the values of the arguments when the function is entered. The void func() {} contrasts with void func(); the former declares that func indeed takes no parameters, whereas the latter is a declaration for a function func for which neither parameters nor their types are specified (a declaration without prototype).

    但是,它们在定义方面还存在差异

    However, they yet differ definition-wise in that


    • 定义 void func1(){} 没有声明原型,而 void func2(void){} 可以,因为()不是参数类型列表,而(void) 是参数类型列表( 6.7。 5.3.10 ):

    • The definition void func1() {} doesn't declare a prototype, whereas void func2(void) {} does, because () is not a parameter type list, whereas (void) is a parameter type list (6.7.5.3.10):


    在列表中唯一项为void的未命名参数的特殊情况指定:该函数没有参数。

    The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.

    以及 6.9.1.7


    如果声明符包括参数类型列表,则
    列表还指定所有参数的类型;这样的声明器还充当函数原型,以供以后在同一翻译单元中调用同一函数。如果声明符包括标识符列表,则参数类型应在随后的声明列表中声明。在这两种情况下,每个参数的类型均按照6.7.5.3中的参数类型列表进行调整;结果类型应为对象类型。

    If the declarator includes a parameter type list, the list also specifies the types of all the parameters; such a declarator also serves as a function prototype for later calls to the same function in the same translation unit. If the declarator includes an identifier list, the types of the parameters shall be declared in a following declaration list. In either case, the type of each parameter is adjusted as described in 6.7.5.3 for a parameter type list; the resulting type shall be an object type.

    func1 的函数定义声明器不会包含参数类型列表,因此该函数没有原型。

    The declarator of function definition for func1 does not contain a parameter type list, and thus the function then doesn't have a prototype.

    void func1(){...} 仍然可以使用任意数量的参数来调用,而调用 void func2(void){则是编译时错误。 ..} 带有任何参数(6.5.2.2):

    void func1() { ... } can still be called with any number of arguments, whereas it is a compile-time error to call void func2(void) { ... } with any arguments (6.5.2.2):


    如果表示被调用函数的表达式具有如果类型为包括原型,则参数的数量应与参数的数量一致。每个参数的类型都应使其值可以分配给具有对应参数类型的非限定版本的对象。

    If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters. Each argument shall have a type such that its value may be assigned to an object with the unqualified version of the type of its corresponding parameter.

    (强调我的)

    这是一个约束,根据标准,该约束表示符合要求的实现必须至少显示一条有关此问题的诊断消息。但是,由于 func1 没有原型,因此不需要执行任何诊断就可以使用一致的实现。

    This is a constraint, which according of the standard says that a conforming implementation must display at least one diagnostic message about this problem. But since func1 doesn't have a prototype, a conforming implementation is not required to produce any diagnostics.

    但是,如果参数数量不等于参数数量,则行为是不确定的 6.5.2.2p6

    However, if the number of arguments does not equal the number of parameters, the behaviour is undefined 6.5.2.2p6:


    如果表示被调用函数的表达式的类型不包括原型,则[...]

    因此,从理论上讲,符合标准的C99编译器是在这种情况下也允许错误或诊断警告。 StoryTeller 提供的证据表明 c语可能会诊断出这一点;但是,我的GCC似乎没有这样做(并且它也可能需要与一些旧的晦涩的代码兼容):

    So in theory a conforming C99 compiler is also allowed to error or diagnose a warning in this case. StoryTeller provided evidence that clang might diagnose this; however, my GCC doesn't seem to do it (and this might also be required for it to be compatible with some old obscure code too):

    void test() { }
    
    void test2(void) { }
    
    int main(void) {
        test(1, 2);
        test2(1, 2);
    }
    

    使用 gcc -std编译上述程序时= c99 test.c -Wall -Werror ,输出为:

    test.c: In function ‘main’:
    test.c:7:5: error: too many arguments to function ‘test2’
         test2(1, 2);
         ^~~~~
    test.c:3:6: note: declared here
     void test2(void) { }
          ^~~~~
    

    也就是说,根本不会根据定义中未声明原型的函数的参数来检查参数( test ),而GCC则认为为原型函数指定任何参数是编译时错误( test2 );任何符合条件的实现都必须对此进行诊断,因为它违反了约束条件。

    That is, the arguments are not checked at all against the parameters of a function whose declaration in definition is not prototyped (test) whereas GCC considers it as a compile-time error to specify any arguments to a prototyped function (test2); any conforming implementation must diagnose this as it is a constraint violation.

    这篇关于c99中的func()vs func(void)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆