【发布时间】:2014-05-28 04:02:56
【问题描述】:
我即将完成著名的“Learn C The Hard Way”在线课程的第 14 课。
在那一课中,它在C 中介绍了前向声明的概念。
代码示例中有两个前向声明。其中一个可以注释掉,代码仍然可以编译,但是另一个不能注释掉。对我来说,它们看起来同样重要。
这是代码。如果它们来自字母表,它会简单地打印出所有字符及其十六进制代码,否则它会跳过它们。
两个编译器输出位于代码的底部。 有人能解释一下为什么一个出错而另一个没有吗?
#include <stdio.h>
#include <ctype.h>
// forward declarations
int can_print_it(char ch); //NOT OK to skip(??)
void print_letters(char arg[]); //OK to skip(??)
void print_arguments(int argc, char *argv[])
{
int i = 0;
for(i = 0; i < argc; i++) {
print_letters(argv[i]);
}
}
void print_letters(char arg[])
{
int i = 0;
for(i = 0; arg[i] != '\0'; i++) {
char ch = arg[i];
if(can_print_it(ch)) {
printf("'%c' == %d ", ch, ch);
}
}
printf("\n");
}
int can_print_it(char ch)
{
return isalpha(ch) || isblank(ch);
}
int main(int argc, char *argv[])
{
print_arguments(argc, argv);
return 0;
}
如果我注释掉第一个前向声明(仅第一个),就会发生这种情况:
cc -Wall -g ex14.c -o ex14
ex14.c: In function ‘print_letters’:
ex14.c:24:9: warning: implicit declaration of function ‘can_print_it’ [-Wimplicit-function-declaration]
ex14.c: At top level:
ex14.c:32:5: error: conflicting types for ‘can_print_it’
ex14.c:33:1: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
ex14.c:24:12: note: previous implicit declaration of ‘can_print_it’ was here
make[1]: *** [ex14] Error 1
make[1]: Leaving directory `/home/andrew/c_tutorials/lesson14/ex14_original'
make: *** [all] Error 2
如果我注释掉第二个声明(仅第二个),就会发生这种情况:
cc -Wall -g ex14.c -o ex14
ex14.c: In function ‘print_arguments’:
ex14.c:13:9: warning: implicit declaration of function ‘print_letters’ [-Wimplicit-function-declaration]
ex14.c: At top level:
ex14.c:17:6: warning: conflicting types for ‘print_letters’ [enabled by default]
ex14.c:13:9: note: previous implicit declaration of ‘print_letters’ was here
make[1]: Leaving directory `/home/andrew/c_tutorials/lesson14/ex14_original'
【问题讨论】:
-
其他答案没有明确提及;但是当你调用一个未声明的函数时,它的行为就像有这个声明:
int functionname();。这是一个 non-prototype 声明,Floris 所描述的是关于非原型声明中参数计数和提升的规则。这些规则也适用于可变参数原型函数中对应于...的参数。当函数具有非原型声明但原型定义时,可能会出现与提升相关的错误。