声明顺序对结构无关紧要?

时间:2013-07-13 05:21:13

标签: c struct declaration

#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);
}

运行上面的代码会出现以下错误

nikunjbanka@ubuntu:~$ 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技能说明程序中原型声明和结构声明的顺序并不重要。我想问一下订单是否重要?

2 个答案:

答案 0 :(得分: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]

表示在gcc编译文件的第3行时,'struct emp'的类型是未知的。编译器通常会尝试推断默认类型&amp;未知struct emp的大小,几乎总是猜错,因为它不知道你最终会如何宣告struct emp

此错误:

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

表示你试图调用函数'f',其实际参数类型与编译文件第3行时gcc(错误)推断的形式参数类型不同。

此错误及相关注释:

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

表示第14行的形式参数类型(现在已知为第4行到第7行声明的类型struct emp)与gcc(再次错误地)在线推断的形式参数类型不匹配3。

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

如果您使用

,您可能还会发现您的代码更具可读性
typedef struct {
   char name[20];
   int  age;
} emp_t;

然后,您可以在后续代码中使用emp_t而不是struct emp

答案 1 :(得分: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()而不包括struct layout的定义。 这是因为编译器可以使用指向已定义但尚未定义的结构的指针 - 前提是您只对它们执行某些操作(存储它们,返回它们,将它们传递给其他函数;将它们与NULL进行比较,或者与其他指针进行比较)同样的事情......将它们转换为其他指针类型...) - 但是如果p是指向未指定结构的指针,则不能进行指针运算,或访问成员(显然)或者请求sizeof(* p)。编译器会通知你: - )