### 14.2 Compiler error messages ¶

``variable' undeclared (first use in this function)` ¶

  In C and C++ variables must be declared before they can be used. This error message indicates that the compiler has encountered a variable name which does not have a corresponding declaration. It can be caused by a missing declaration, or a typing error in the name. Variable names are case-sensitive, so `foo` and `Foo` represent different variables. To keep the output short, only the first use of an undeclared variable is reported.

  Example:

      int
      main (void)
      {
        int i;
        j = 0;     /* undeclared */
        return j;
      }

  The variable `j` is not declared and will trigger the error ``j' undeclared`.

`parse error before `...'` ¶
`syntax error`

  These error messages occur when the compiler encounters unexpected input, i.e. sequences of characters which do not follow the syntax of the language. The error messages can be triggered by a missing close bracket, brace or semicolon preceding the line of the error, or an invalid keyword.

  Example:

      #include <stdio.h>

      int
      main (void)
      {
        printf ("Hello ")     /* missing semicolon */
        printf ("World!\n");
        return 0;
      }

  There is a missing semicolon after the first call to `printf`, giving a `parse error`.

`parse error at end of input` ¶

  This error occurs if the compiler encounters the end of a file unexpectedly, such as when it has parsed an unbalanced number of opening and closing braces. It is often caused by a missing closing brace somewhere.

  Example:

      #include <stdio.h>

      int
      main (void)
      {
        if (1) {
          printf ("Hello World!\n");
          return 0;  /* no closing brace */
      }

  An additional closing brace is needed in this program to prevent the error `parse error at end of input`.

`warning: implicit declaration of function `...'` ¶

  This warning is generated when a function is used without a prototype being declared. It can be caused by failing to include a header file, or otherwise forgetting to provide a function prototype.

  Example:

      int
      main (void)
      {
        printf ("Hello World!\n");  /* no header */
        return 0;
      }

  The system header file `stdio.h` is not included, so the prototype for `printf` is not declared. The program needs an initial line `#include <stdio.h>`.

`unterminated string or character constant` ¶

  This error is caused by an opening string or character quote which does not have a corresponding closing quote. Quotes must occur in matching pairs, either single quotes `'a'` for characters or double quotes `"aaa"` for strings.

  Example:

      #include <stdio.h>

      int
      main (void)
      {
        printf ("Hello World!\n);  /* no closing quote */
        return 0;
      }

  The opening quote for the string in this program does not have a corresponding closing quote, so the compiler will read the rest of the file as part of the string.

`character constant too long` ¶

  In C and C++ character codes are written using single quotes, e.g. `'a'` gives the ASCII code for the letter a (67), and `'\n'` gives the ASCII code for newline (10). This error occurs if single quotes are used to enclose more than one character.

  Example:

      #include <stdio.h>

      int
      main (void)
      {
        printf ('Hello World!\n');  /* wrong quotes */
        return 0;
      }

  The program above confuses single-quotes and double-quotes. A sequence of characters should be written with double quotes, e.g. `"Hello World!"`. This same problem occurs in the following C++ program,

      #include <iostream>

      int
      main (void)
      {
        std::cout << 'Hello World!\n';  // wrong quotes
        return 0;
      }

  This error can also occur if the forward slash and backslash are confused in an escape sequence, e.g. using `'/n'` instead of `'\n'`. The sequence `/n` consists of two separate characters, ‘`/`’ and ‘`n`’.

  Note that according to the C standard there is no limit on the length of a character constant, but the value of a character constant that contains more than one character is implementation-defined. Recent versions of GCC provide support multi-byte character constants, and instead of an error the warnings `multiple-character character constant` or `warning: character constant too long for its type` are generated in this case.

`warning: initialization makes integer from pointer without a cast` ¶

  This error indicates a misuse of a pointer in an integer context. Technically, it is possible to convert between integer and pointer types, but this is rarely needed outside system-level applications. More often, this warning is the result of using a pointer without dereferencing it (e.g. writing `int i = p` instead of `int i = *p`).

  This warning can also occur with `char` and `char *` types, since `char` is an integer type.

  Example:

      int
      main (void)
      {
        char c = "\n";  /* incorrect */
        return 0;
      }

  The variable `c` has type `char`, while the string `"\n"` evaluates to a `const char *` pointer (to a 2-byte region of memory containing the ASCII value for newline followed by a zero byte `'\0'`, since strings are null-terminated). The ASCII code for newline can be found using `char c = '\n';`

  Similar errors can occur with misuse of the macro `NULL`,

      #include <stdlib.h>

      int
      main (void)
      {
        int i = NULL;  /* incorrect */
        return 0;
      }

  In C, the macro `NULL` is defined as `((void *)0)` in `stdlib.h` and should only be used in a pointer context.

`dereferencing pointer to incomplete type` ¶

  This error occurs when a program attempts to access the elements of struct through a pointer without the layout of the struct being declared first. In C and C++ it is possible to declare pointers to structs before declaring their struct layout, provided the pointers are not dereferenced—this is known as forward declaration.

  Example:

      struct btree * data;

      int
      main (void)
      {
        data->size = 0;  /* incomplete type */
        return 0;
      }

  This program has a forward declaration of the `btree` struct `data`. However, the definition of the struct is needed before the pointer can be dereferenced to access individual members.

`warning: unknown escape sequence `...'` ¶

  This error is caused by an incorrect use of the escape character in a string. Valid escape sequences are:

  | `\n` newline | `\t` tab
  | `\b` backspace | `\r` carriage return
  | `\f` form feed | `\v` vertical tab
  | `\a` alert (bell)

  The combinations `\\`, `\'`, `\"` and `\?` can be used for individual characters. Escape sequences can also use octal codes `\0`–`\377` and hexadecimal codes `\0x00`–`\0xFF`.

  Example:

      #include <stdio.h>

      int
      main (void)
      {
        printf ("HELLO WORLD!\N");
        return 0;
      }

  The escape sequence `\N` in the program above is invalid—the correct escape sequence for a newline is `\n`.

`warning: suggest parentheses around assignment used as truth value` ¶

  This warning highlights a potentially serious error, using the assignment operator ‘`=`’ instead of the comparison operator ‘`==`’ in the test of a conditional statement or other logical expression. While the assignment operator can be used as part of a logical value, this is rarely the intended behavior.

  Example:

      #include <stdio.h>

      int
      main (void)
      {
        int i = 0;
        if (i = 1) {  /* = should be == */
          printf ("unexpected result\n");
        }
        return 0;
      }

  The test above should be written as `if (i == 1)`, otherwise the variable `i` will be set to `1` by the evaluation of the if statement itself. The operator ‘`=`’ both assigns and returns the value of its right-hand side, causing the variable `i` to be modified and the unexpected branch taken. Similar unexpected results occur with `if (i = 0)` instead of `if (i == 0)`, except that in this case the body of the `if` statement would never be executed.

  This warning is suppressed if the assignment is enclosed in additional parentheses to indicate that it is being used legitimately.

`warning: control reaches end of non-void function` ¶

  A function which has been declared with a return type, such as `int` or `double`, should always have a `return` statement returning a value of the corresponding type at all possible end points—otherwise its return value is not well-defined. Functions declared `void` do not need `return` statements.

  Example:

      #include <stdio.h>

      int
      display (const char * str)
      {
        printf ("%s\n", str);
      }

  The program above reaches the end of the `display` function, which has a return type of `int`, without a `return` statement. An additional line such as `return 0;` is needed.

  When using `gcc` the `main` function of a C program must return a value of type `int` (the exit status of the program). In C++ the `return` statement can be omitted from the `main` function—the return value of the C++ `main` function defaults to 0 if unspecified.

`warning: unused variable `...'` ¶
`warning: unused parameter `...'`

  These warnings indicate that a variable has been declared as a local variable or in the parameters of a function, but has not been used anywhere. An unused variable can be the result of a programming error, such as accidentally using the name of a different variable in place of the intended one.

  Example:

      int
      foo (int k, char * p)
      {
        int i, j;
        j = k;
        return j;
      }

  In this program the variable `i` and the parameter `p` are never used. Note that unused variables are reported by `-Wall`, while unused parameters are only shown with `-Wall -W`.

`warning: passing arg of ... as ... due to prototype` ¶

  This warning occurs when a function is called with an argument of a different type from that specified in the prototype. The option `-Wconversion` is needed to enable this warning. See the description of `-Wconversion` in Additional warning options for an example.

`warning: assignment of read-only location` ¶
`warning: cast discards qualifiers from pointer target type`
`warning: assignment discards qualifiers ...`
`warning: initialization discards qualifiers ...`
`warning: return discards qualifiers ...`

  These warnings occur when a pointer is used incorrectly, violating a type qualifier such as `const`. Data accessed through a pointer marked as `const` should not be modified, and the pointer itself can only be assigned to other pointers that are also marked `const`.

  Example:

      char *
      f (const char *s)
      {
        *s = '\0';  /* assigns to read-only data */
        return s;   /* discards const */
      }

  This program attempts to modify constant data, and to discard the `const` property of the argument `s` in the return value.

`initializer element is not a constant` ¶

  In C, global variables can only be initialized with constants, such as numeric values, `NULL` or fixed strings. This error occurs if a non-constant value is used.

  Example:

      #include <stdio.h>

      FILE *stream = stdout;  /* not constant */
      int i = 10;
      int j = 2 * i;          /* not constant */

      int
      main (void)
      {
        fprintf (stream, "Hello World!\n");
        return 0;
      }

  This program attempts to initialize two variables from other variables. In particular, the stream `stdout` is not required to be a constant by the C standard (although on some systems it is a constant). Note that non-constant initializers are allowed in C++.