我正在做一本旧的C书[ANSIC的第一本书]中的一些例子,在试图编译以下示例代码时遇到了错误:
#include <stdio.h>
struct tele_typ {
char name[30];
char phone_no[15];
struct tele_typ *nextaddr;
};
main() {
struct tele_typ t1 = {"Acme, Sam", "(201) 555-6678"};
struct tele_typ t2 = {"Dolan, Edith", "(213) 682-3104"};
struct tele_typ t3 = {"Lanfrank, John", "(415) 718-4581"};
tele_typ *first; /* create a pointer to a structure */
first = &t1; /* store t1's address in first */
t1.nextaddr = &t2; /* store t2's address in t1.nextaddr */
t2.nextaddr = &t3; /* store t3's address in t2.nextaddr */
t3.nextaddr = NULL; /* store the NULL address in t3.nextaddr */
printf("n%s %s %s",first->name,t1.nextaddr->name,t2.nextaddr->name);
}
以及来自gcc newstruct.c -o newstruct
:的输出
newstruct.c: In function 'main':
newstruct.c:13:3: error: unknown type name 'tele_typ'
newstruct.c:15:9: warning: assignment from incompatible pointer type [enabled by default]
newstruct.c:20:28: error: request for member 'name' in something not a structure or union
这是关于链表的第10.4章。这本书有错误吗?或者标准/gcc version 4.6.2 20120120 (prerelease)
中有什么变化?非常感谢。
我无法再现第一个警告;你确定你粘贴在这里的代码就是给你警告的代码吗?
错误unknown type name 'tele_typ'
很容易修复:您已经声明了一个类型struct tele_typ
,但在行前没有struct
:
tele_typ *first; /* create a pointer to a structure */
如果您将其更改为:
struct tele_typ *first; /* create a pointer to a structure */
它编译时不会出错。(在我的gcc-4.5.real(Ubuntu/Linaro 4.5.2-8ubuntu4)4.5.2中也没有警告。)
如果你想按原样编译函数体,那么你还需要添加:
typedef struct tele_typ tele_typ;
紧接在struct tele_typ
定义之后:
struct tele_typ {
char name[30];
char phone_no[15];
struct tele_typ *nextaddr;
};
typedef struct tele_typ tele_typ;
但我有点担心一本C书没有给main()
函数一个返回类型或类型的参数。int main(int argc, char* argv[])
或int main(int argc, char** argv)
是常见的,任何偏离这两个选项的书都会让我觉得有点奇怪。《C程序设计语言》是一本很好的书;由于它的清晰性和正确性,很难对其进行改进。考虑切换到原始版本。
您的代码有以下错误,其中一些是小错误。
-
CCD_ 10需要是CCD_。
main()
表单是一个旧式的定义;从1989年的ANSI C标准开始,它就被弃用了,在1999年的ISO C标准中,它完全无效,该标准删除了"隐式int"规则。使用CCD_ 13而不是CCD_ 14使得CCD_;()
形式仍然有效,但自1989年以来一直被弃用。出于向后兼容性的考虑,许多C编译器会接受这样的旧式功能,但至少会在一致性模式下警告它们。您应该了解如何为编译器启用此类警告。 -
CCD_ 17需要是CCD_。这是主要问题。(添加
typedef
是解决这一问题的另一种方法,但这是绝对没有必要的。代码已经将该类型称为struct tele_typ
;您只需要一致地这样做。)请注意,在C++中,您可以将该类型称作struct tele_typ
,也可以仅称作tele_typ
——当然,C++是一种不同的语言,具有不同的规则。 -
您应该在打印字符串的结尾处有一个
n
;你一开始并不需要它。printf("%s %s %sn",first->name,t1.nextaddr->name,t2.nextaddr->name);
-
在
main
函数中,在关闭}
之前应该有一个return 0;
。根据1989年ANSI C标准(或等效的1990年ISO C标准),从main
的末尾掉下来而不返回值会向调用环境返回未定义的结果。从1999年的标准来看,从main
的末尾掉下来是隐含的return 0;
,但明确它没有害处。
启用警告后,一些编译器可能会抱怨t1
、t2
和t3
的声明中缺少初始值设定项,因为您没有为nextaddr
成员提供值。这是可以的,因为(a)只要你有一个初始化器,任何未指定的成员都会初始化为零(在指针的情况下,初始化为空指针),并且(b)你稍后会显式地为这些成员赋值。
我看到你在用gcc。要获得一组好的警告,你可以使用这个:
gcc -ansi -pedantic -Wall -Wextra
如果要针对较新版本的C标准进行测试,请将-ansi
更改为-std=c99
或-std=c1x
。请注意,使用-ansi
或-std=...
选项之一可能会禁用一些非标准扩展。有时您需要编写不可移植的代码;在这种情况下,您可以放弃该选项,可能还会放弃-pedantic
。但是这个程序不使用任何扩展,也不需要。
您在函数main的第4行开头缺少"struct"。它应该读取
struct tele_typ *first;
这在C++中会很好,因为"struct"关键字是可选的,但在C中却是必需的。
此行错误:
tele_typ *first; /* create a pointer to a structure */
您忘记了struct
关键字。
此外,main
实际上应该声明为返回int
,并以return
结束。
使用typedef肯定是一种方法。
只是一个狡辩:前导双下划线是保留的;应用程序程序员不应该使用它们,因为它们可能会导致名称空间问题。
Kernahan&里奇的书《C编程语言》是最好的书。然而,对于初学者来说,这是一项艰巨的任务。发帖人的书显然错了!
您必须更改指针结构声明,以获得以下内容:
struct tele_typ *first; /* create a pointer to a structure */
为什么,因为您还没有将结构tele_type
定义为直接类型,所以您仍然必须使用struct tele_typ
来指向它。
如果你在另一边做了这样的事情:
typedef struct TELE_TYP {
char name[30];
char phone_no[15];
struct TELE_TYP *nextaddr;
}tele_typ;
你可以调用之前定义的类型,如果你写了:
tele_typ *first;
长话短说,这本书错了:p