简体   繁体   中英

Errors compiling example from ANSI C book, Linked Lists chapter

I am doing some examples out of an older C book [A First Book of ANSI C] and am getting an error while trying to compile this example code:

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

..and the output from 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

It's chapter 10.4 on Linked Lists. Is there an error in the book? or has something changed in the standards/ gcc version 4.6.2 20120120 (prerelease) ? Thank you!

I couldn't reproduce the first warning; are you sure the code you've pasted here is the code that gives you the warning?

The error unknown type name 'tele_typ' is easy to fix: you've declared a type struct tele_typ , but don't have the struct in front of the line:

  tele_typ *first;    /* create a pointer to a structure */

If you change this to:

  struct tele_typ *first;    /* create a pointer to a structure */

It'll compile without error. (And also without warnings in my gcc-4.5.real (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2.)

If you wanted to compile the function body exactly as-is, then you'd also want to add:

typedef struct tele_typ tele_typ;

immediately after the struct tele_typ definition:

struct tele_typ {
  char name[30];
  char phone_no[15];
  struct tele_typ *nextaddr;
};

typedef struct tele_typ tele_typ;

But I'm a little worried about a C book that doesn't give the main() function a return type or typed parameters. int main(int argc, char* argv[]) or int main(int argc, char** argv) is usual, and any book that deviates from these two options strikes me as a little strange. The C Programming Language is a fine book; it is hard to improve upon it for its clarity and correctness. Consider switching to the original.

You're missing the 'struct' at the beginning of the 4th line of function main. It should read

struct tele_typ *first;

That would have worked fine in C++, since the 'struct' keyword is optional, but in C it's required.

This line is wrong:

tele_typ *first;    /* create a pointer to a structure */

You forgot the struct keyword.

Also, main should really be declared as returning an int , and end with a return .

Your code has the following errors, some of them minor.

  1. main() needs to be int main(void) . The main() form is an old-style definition; it's deprecated as of the 1989 ANSI C standard, and flat-out invalid under the 1999 ISO C standard, which dropped the "implicit int" rule. Using (void) rather than () makes it explicit that main has no parameters; the () form is still valid, but has been deprecated since 1989. Many C compilers will accept old-style features like this for the sake of backward compatibility, but will at least warn about them in conforming mode. You should find out how to enable such warnings for your compiler.

  2. tele_typ *first; needs to be struct tele_typ *first; . This is the main problem. (Adding a typedef is another way to work around this, but it's absolutely unnecessary. The code already refers to the type as struct tele_typ ; you just need to do so consistently.) Note that in C++ you can refer to the type either as struct tele_typ or just as tele_typ -- of course, C++ is a different language with different rules.

  3. You should have a \\n at the end of the string you print; you don't need it at the beginning.

    printf("%s %s %s\\n",first->name,t1.nextaddr->name,t2.nextaddr->name);

  4. You should have a return 0; before the closing } in your main function. As of the 1989 ANSI C standard (or the equivalent 1990 ISO C standard), falling off the end of main without returning a value returns an undefined result to the calling environment. As of the 1999 standard, falling off the end of main does an implicit return 0; , but there's no harm in being explicit about it.

With warnings enabled, some compilers may complain about missing initializers on the declarations of t1 , t2 , and t3 , since you didn't provide values for the nextaddr member. This is ok, since (a) as long as you have an initializer, any unspecified members are initialized to zero (in the case of a pointer, to a null pointer), and (b) you explicitly assign values to these members later on.

I see that you're using gcc. To get a good set of warnings, you can use this:

gcc -ansi -pedantic -Wall -Wextra

Change the -ansi to -std=c99 or -std=c1x if you want to test against a newer version of the C standard. Note that using -ansi or one of the -std=... options may disable some non-standard extensions. Sometimes you need to write non-portable code; in that case, you can drop that option, and probably the -pedantic as well. But this program doesn't use any extensions, and doesn't need to.

You have to change the pointer structure declaration for something like this:

struct tele_typ *first;    /* create a pointer to a structure */

Why, because you haven't already defined the structure tele_type as a direct type, you still have to point at it using struct tele_typ .

If you on the other side had done something like this:

typedef struct TELE_TYP {
  char name[30];
  char phone_no[15];
  struct TELE_TYP *nextaddr;
}tele_typ;

You would have been able to call for the previously defined type and it would have been ok if you had written:

tele_typ *first;

Long story short, the book is wrong :P

Using the typedef is definitely the way to go.

Just a quibble: Leading double underscores are reserved; they should NOT be used by application programmers because they could cause namespace problems.

The Kernahan & Ritche book "The C Programming Language" is the best book bar none. It is a hard slog for the beginner, however. The book the person who Posted the question has is obviously wrong!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM