Search code examples
cgcclinked-listansi-c

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!


Solution

  • 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.