我正在使用较旧的C书[ANSI C的第一本书]做一些示例,并且在尝试编译此示例代码时遇到错误:
#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)
中有什么变化?谢谢!
答案 0 :(得分:3)
我无法重现第一个警告;你确定你在这里粘贴的代码是给你警告的代码吗?
错误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;
但是我有点担心一本不给main()
函数提供返回类型或类型参数的C书。 int main(int argc, char* argv[])
或int main(int argc, char** argv)
是常见的,任何偏离这两个选项的书都会让我觉得有些奇怪。 The C Programming Language是一本好书;它的清晰度和正确性很难改进。考虑切换到原始版本。
答案 1 :(得分:2)
你错过了函数main第4行开头的'struct'。它应该读
struct tele_typ *first;
这在C ++中运行良好,因为'struct'关键字是可选的,但在C中它是必需的。
答案 2 :(得分:2)
这一行错了:
tele_typ *first; /* create a pointer to a structure */
您忘记了struct
关键字。
此外,main
应该真正声明为返回int
,并以return
结尾。
答案 3 :(得分:2)
您的代码有以下错误,其中一些是次要错误。
main()
需要int main(void)
。 main()
形式是旧式定义;它在1989 ANSI C标准中被弃用,并且根据1999 ISO C标准的平坦无效,它取消了“隐含int”规则。使用(void)
而非()
可明确main
没有参数; ()
表单仍然有效,但自1989年以来一直被弃用。许多C编译器都会接受这样的旧式功能,以便向后兼容,但至少会在符合模式下警告它们。您应该了解如何为编译器启用此类警告。
tele_typ *first;
需要struct tele_typ *first;
。这是主要问题。 (添加typedef
是解决此问题的另一种方法,但这绝对没有必要。代码已经将类型称为struct tele_typ
;您只需要一致地这样做。)请注意,在C ++中,您可以将类型称为struct tele_typ
或仅作为tele_typ
- 当然,C ++是一种具有不同规则的不同语言。
您打印的字符串的 end 应该有一个\n
;你一开始就不需要它。
printf("%s %s %s\n",first->name,t1.nextaddr->name,t2.nextaddr->name);
在return 0;
功能关闭}
之前,您应该有一个main
。从1989 ANSI C标准(或等效的1990 ISO C标准)开始,在main
结束时不返回值会向调用环境返回未定义的结果。从1999年的标准来看,main
的结尾处有一个隐含的return 0;
,但明确它是没有害处的。
启用警告后,某些编译器可能会抱怨t1
,t2
和t3
的声明缺少初始值设定项,因为您没有为{{1}提供值会员这没关系,因为(a)只要你有一个初始化器,任何未指定的成员都被初始化为零(在指针的情况下,指向空指针),以及(b)你稍后明确地为这些成员赋值
我看到你正在使用gcc。要获得一组好的警告,您可以使用:
nextaddr
如果要针对较新版本的C标准进行测试,请将gcc -ansi -pedantic -Wall -Wextra
更改为-ansi
或-std=c99
。请注意,使用-std=c1x
或其中一个-ansi
选项可能会禁用某些非标准扩展。有时您需要编写不可移植的代码;在这种情况下,您可以删除该选项,也可以删除-std=...
。但是这个程序不使用任何扩展,也不需要。
答案 4 :(得分:1)
您必须更改指针结构声明,如下所示:
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
答案 5 :(得分:1)
使用typedef绝对是最佳选择。
只是一个狡辩:保留领先的双下划线;应用程序员不应该使用它们,因为它们可能会导致命名空间问题。
Kernahan&amp; Ritche书“The C Programming Language”是最好的书吧。然而,这对初学者来说是一个艰难的过程。发布问题的人的书显然是错误的!