4

我刚刚阅读:“C void arguments”,关于 C 中这些函数定义之间的差异:

int f(void)

int f()

理解第二种形式意味着一个返回整数的函数,它接受任意数量的参数,我想知道我们如何才能真正访问和使用这些未知参数

我很想获得示例代码和解释。

另外,我知道 C 中 Varargs 的机制(带有va_arg, va_end,va_start函数),并且很高兴听到这种机制与上述形式之间的差异f()

十分感谢!

4

4 回答 4

7

第二个版本不接受可变数量的参数,它接受固定(但未指定)的参数序列。实际上,它声明了函数,但没有原型化函数。因此,不会检查对函数的调用是否有有效类型。编译器通常会查看对函数的第一次调用,并根据第一次调用中找到的类型检查其他调用。

这就是为什么,如果你省略#include <stdio.h>,第一次调用printf是可以接受的,但是任何printf不同类型的调用都会产生错误。例如。

int main() {
    printf("hello");        //<--- accepted, compiler may assume `int printf(char *);`
    printf("%s", "world");  //<--- error, type mismatch
}

要让一个函数接受一个可变数字,它必须至少有一个固定参数,然后是 token ...

int f (int first, ...);

您将需要包含stdarg.h头文件。并且该函数可以使用宏访问参数。

void f (int c,...){
    va_list ap;
    va_start(ap, c);
    for(;c--;)
        printf("%d", va_arg(ap,int));
    va_end (ap);
}

将固定参数作为剩余参数的计数很方便。您还需要以某种方式确定每个参数的类型。在这个例子中,它们都被假定为int

于 2013-09-13T18:08:40.033 回答
4
 int f(void);

声明f为不带参数并返回int结果的函数,而

 int f();

声明f为接受固定但未指定数量和类型的参数的函数(当然,返回int结果)。

给定这样的声明,必须在某处有一个实际定义参数的定义。如果它不带参数,它可能被定义为:

int f() {
    return 42;
};

如果它需要 2 个int参数,它可能被定义为:

int f(int x, int y) {
    return x + y;
}

任何一个定义都与 兼容int f();,但只有第一个定义与 兼容int f(void)

指定参数类型的函数声明,或者,作为一种特殊情况,使用void关键字来指定没有参数,是原型这样做的函数声明,例如int f();旧式声明。

除非你被困在使用几十年前不支持原型的 pre-ANSI 编译器,或者你正在维护非常旧的代码并且没有时间或其他资源来更新它,否则没有理由不使用原型。如果你调用一个没有可见原型的函数,你仍然需要传递正确数量和类型的参数;不同之处在于编译器将无法告诉您调用是否不正确。

(您可以定义一个函数,该函数采用可变数量和类型的参数;printf就是一个例子。这是使用, ...符号完成的。函数本身使用定义的特性<stdarg.h>来处理参数。但这与声明无关显示在您的问题中。)

这是一个使用过时的旧式函数声明和定义的小程序:

#include <stdio.h>
#include <stdlib.h>

int add();

int main(argc, argv)
int argc;
char **argv;
{
    if (argc == 3) {
        /* NOTE: atoi() does no error checking */
        printf("sum = %d\n", add(atoi(argv[1]), atoi(argv[2])));
    }
    else {
        fprintf(stderr, "Usage: %s x y\n", argv[0]);
        exit(EXIT_FAILURE);
    }
}

int add(x, y)
int x, y;
{
    return x + y;
}

请注意,如果我写了add(1, 2, 3, 4)or add("foo", "bar"),编译器就不会发现错误;该程序只是行为不端。

这是一个使用现代函数声明和定义的等效程序:

#include <stdio.h>
#include <stdlib.h>

int add(int x, int y);

int main(int argc, char **argv) {
    if (argc == 3) {
        /* NOTE: atoi() does no error checking */
        printf("sum = %d\n", add(atoi(argv[1]), atoi(argv[2])));
    }
    else {
        fprintf(stderr, "Usage: %s x y\n", argv[0]);
        exit(EXIT_FAILURE);
    }
}

int add(int x, int y) {
    return x + y;
}

可见的原型意味着编译器能够诊断不正确的调用。

于 2013-09-13T18:47:50.333 回答
1

至于f()表格: 点击

一个示例,一个类似 printf 的函数,可以将十进制数字或字符串打印到文件描述符中:

#include <stdarg.h>
/* Formatted printing into a file descriptor */                          
int printfd(int fd, char *fmt, ...)                                      
{                                                                        
    int bytes = 0;                                                   
    int i_val = 0;                                                   
    va_list va;                                                      
    va_start(va, fmt);                                               
    while (*fmt) {                                                   
            char *perc = strchr(fmt, '%');                           
            int len = perc == NULL ? strlen(fmt) : perc - fmt;       
            if (len) {                                               
                    bytes += write(fd, fmt, len);                    
                    fmt += len;                                      
            } else {                                                 
                    fmt = perc + 1;                                  
                    if (*fmt == 0)                                   
                            continue;                                
                    else if (*fmt == '%')                            
                            bytes += write(fd, fmt, 1);              
                    else if (*fmt == 'd')                            
                            bytes += writedec(fd, va_arg(va, int));  
                    else if (*fmt == 's')                            
                            bytes += writestr(fd, va_arg(va, char*));
                    fmt++;                                           
            }                                                        
    }                                                                
    va_end(va);                                                      
    return bytes;                                                    
}                                                                        
于 2013-09-13T18:10:53.907 回答
1

int f(void)表示返回不带参数的 int 的函数。

您可以查看此示例以了解使用 int f() 的结果

#include <stdio.h>

void f();

int main() {
  f(); /* prints some garbage */
  f(16);  /* prints 16 */ 
  return 0;
}

void f(a1)
  int a1;
{
   printf("%d\n", a1);
}

还有这个:-

#include <stdio.h>
    #include <stdlib.h>
    int f();
    int f(int x) {
        return x;
    }
    int main (int argc, char *argv[]) {
         printf ("%d\n", f(atoi(argv[1])));
         return 0;
    }

pax> gcc -Wall --std=c99 -o qq qq.c
pax> ./qq 42
42
于 2013-09-13T18:11:14.013 回答