2013-07-13 55 views
0
#include <stdio.h> 
#include <stdlib.h> 
void f(struct emp); 
struct emp{ 
char name[20]; 
int age; 
}; 
int main(){ 
    struct emp e = {"nikunj", 23} ; 
    f(e); 
    return 0; 
} 

void f(struct emp e){ 
    printf("%s %d\n", e.name, e.age); 
} 

运行上面的代码提供了以下错误声明的顺序对结构无关紧要吗?

[email protected]:~$ gcc hello2.c -o main.out 
hello2.c:3:15: warning: ‘struct emp’ declared inside parameter list [enabled by default] 
hello2.c:3:15: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default] 
hello2.c: In function ‘main’: 
hello2.c:10:2: error: type of formal parameter 1 is incomplete 
hello2.c: At top level: 
hello2.c:14:6: error: conflicting types for ‘f’ 
hello2.c:3:6: note: previous declaration of ‘f’ was here 

但是,这本书测试你的C技能说,原型声明和结构声明的程序中的顺序并不重要。我想问问订单是否重要?

回答

4

是的顺序绝对重要。

重新排序代码,使得struct emp的定义出现在f的函数原型之前。

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

struct emp{ 
    char name[20]; 
    int age; 
}; 

void f(struct emp); 

... 

GCC实际上是想告诉你,你在错误的顺序做的事情,但是编译器的消息是有点混乱,如果这是你第一次通过他们阅读。

这两个警告:

hello2.c:3:15: warning: ‘struct emp’ declared inside parameter list [enabled by default] 
hello2.c:3:15: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default] 

表明“结构EMP”的类型在编译的文件的第3行的时候GCC是不知道的。编译器通常会尝试推断默认类型&尺寸为未知的struct emp,并且几乎总是错误地猜测,因为它不知道如何最终将声明struct emp

此错误:

hello2.c:10:2: error: type of formal parameter 1 is incomplete 

表明您尝试调用函数“F”与比正式参数类型不同的是海湾合作委员会(错误地)推断,当它编译3号线的实际参数类型文件。

此错误和相关注意事项:

hello2.c:14:6: error: conflicting types for ‘f’ 
hello2.c:3:6: note: previous declaration of ‘f’ was here 

表明,第14行正式参数类型(这是目前已知的类型struct emp你行宣布4至7)不匹配形式参数键入gcc(再次错误地)在行3上推断。

底线:在引用它们的原型之前定义所有类型,并且应该没问题。

您也可能会发现你的代码,如果你使用

typedef struct { 
    char name[20]; 
    int age; 
} emp_t; 

然后你就可以使用emp_t而非struct emp整个后续代码的可读性。

0

还有另一种选择 - 这种变化将解决这个问题太:

#include <stdio.h> 
#include <stdlib.h> 
struct emp; /* <--- add this line */ 

void f(struct emp); /* <-- now this refers to that */ 
struct emp{  /* <-- and this defines the same thing */ 
char name[20];  /* and you didn't need to move things around. */ 
int age; 
}; 

在一个复杂的项目并不总是容易解决所有的顺序问题,这可能是有帮助的。请注意,当f实际上是f(struct emp *) - not f(struct emp)时 - 那么您可以在不包含结构布局的定义的情况下定义f()。 这是因为编译器可以使用指向已命名但尚未定义的结构的指针 - 只要您只对它们执行某些操作(存储它们,返回它们,将它们传递给其他函数;将它们与NULL或其他指针进行比较同样的东西......将它们转换为其他指针类型......) - 但是如果p是指向未指定结构体的指针,则不能执行指针算术或访问成员(显然)或要求sizeof(* p) 。编译器会让你知道:-)