This page (originally an Appendix in the book) is intended to help you understand and fix common compiler errors that you may encounter. The messages are ordered alphabetically. Since many messages can occur on various identifiers (e.g., different variables may be undefined), id is used whenever an identifier appears in the message, and that message is alphabetized accordingly (so if you have an error that starts with x, look in alphabetical order for i, not x).
These error messages come from gcc—you will get different wording from other compilers (including LLVM, which is what you generally get if you type gcc on Mac OSX). This list is by no means complete, but we have included< many common ones. If you come across an error that is not listed here, please use the following form (coming soon!) to let us know about it.

  • #include expects "FILENAME" or <FILENAME>
    You wrote a #include directive, but the filename following it had neither <> nor "" around it. It should look like #include <stdio.h> for standard include files, or #include "myHeader.h" for ones you wrote yourself.

  • [C++] '>>' should be '> >' within a nested template argument list
    Whitespace is required between two close angle brackets for nested template arguments. The designers of C++ made this rule to simplify the problems of distinguishing the two close brackets for nested templates from the >> operator during parsing. See Section 17.3.4.

  • a label can only be part of a statement and a declaration is not a statement
    Due to a quirk of the C language, you cannot place the declaration of a variable immediately after a label (such as a case label). Instead of writing
    case 1:
     int y;
     ...
     break;
    
    Either, write:
    case 1: {
     int y;
     ...
     break;
     }
    
    or declare y outside of the switch statement.

  • array subscript is not an integer
    This error means that you are trying to index into an array with a type which is not an integer---such as float, double, a pointer, a struct, etc....---which is illegal. Remember that the array subscript (the number inside the square brackets) specifies which element of the array you want. Requesting the 3.47th element of an array does not make sense.

    • If the subscript is a real type (float, or double), then maybe you meant to convert it to an int first. You can do so either by explicitly casting, or making a new int variable and assigning to it (which implciitly casts). If you want to round in a different way than truncation, you should use the appropriate function for the rounding you want.

    • If the subscript is a pointer to an integer type, you may have meant to dereference it.

    • If the subscript is a struct, you may have meant to select a particular member out of it with the dot (.) operator.

    • If it is a pointer to a struct, you may have meant to select a particular member out of it with the arrow (->) operator.

  • assignment discards qualifiers from pointer target type
    This error message means that you are assigning a pointer declared with modifiers (also called ``qualifiers'') on its type (such as const) to a pointer that does not have these modifiers. Such a situation is an error because it allows you to create an alias for a box which accesses it in a different way than it was originally declared. For example, if you write
    const char * str = ``something'';
    ...
    ...
    char * modifiable = str;  //illegal!
    modifiable[0] = 'X';  //would be legal, but bad.
    
    The code exhibits improper behavior (modifying read-only locations), but the only place that the error can be noticed by the compiler is on line 4, where the assignment converts a const char * to a char *. The modification on line 5 is legal since modifiable points at (mutable) chars, not const chars.

  • assignment makes integer from pointer without a cast
    This error means that you have an assignment statement where the right side has a pointer type (such as int *, char *, int **, etc....), and the left side names a box which has an integer type (such as int, unsigned int, long, ...). Typically this problem arises either (1) because you forgot to dereference the pointer on the right side:
     int * p = ...;
     int x = ...;
     ...
     x = p;  //maybe you meant x = *p;
    
    or (2) because you have a string that you expect to have the textual representation of a number, and have forgotten that you cannot perform the conversion with a cast (either implicit or explicit). See Section 10.1.5 for a deatiled discussion of (2). Note that inserting an explicit cast is almost never the solution you want. Explicitly casting from the pointer type to int is only the right answer if you plan to explicitly manipulate the address numerically, in ways other than standard pointer arithmetic (see Section 8.7). In such a case (which would generally mean you are sufficiently advanced in your programming skill that you no longer need to consult this reference for common errors), your integer type should be intptr_t or uintptr_t.

  • assignment makes pointer from integer without a cast
    This error means that you have an assignment statement where the right side has an integer type (such as int, unsigned int, long, ...), and the left side names a box which has a pointer type (such as int *, char *, int **, etc....). This error typically either means that (1) you forgot to derference the left side:
      int * p = ...;
      int x = ...;
      ...
      p = x; //maybe you meant *p = x;
    
    or (2) that you forgot to take the address of the right side:
      int * p = ...;
      int x = ...;
      ...
      p = x; //maybe you meant p = &x;
    
    Draw a picture of what you are trying to do, and see if it corresponds with either of these changes. If it is one of these two, then correct it appropriately. If it is not, carefully think about how your manipulations of the picture correspond to pointer operations, and correct that part of the code accordingly. See the note in the previous error about why a cast is not the correct solution for anything you are likely to be doing.

  • assignment of read-only variable 'id'
    OR
    assignment of read-only location
    Either of these two error message means that you are trying to modify a location (``box'') that you have said cannot/should not be modified---typically because the way you are trying to name the box has been declared with the const modifier. The first message is what you get if you have a variable declared const and try to assign to it. The second message arises when you refer to the box indirectly (e.g., through a const pointer). If the pointer is const because it points at a string literal, and you need to modify that string, you need to copy the string into a modifiable area of memory (see Section 10.1.1 and Section 10.1.2). Otherwise, if you are sure that you should be modifying this box, think carefully about why it was declared const in the first place, and if you are convinced that that modifier can be removed, then you can fix this error by doing so. Note that this approach may cause other errors if this name is an alias for another name which was also declared const. You may also find that this box really should be const, and thus you should not be modifying it. In this case, you should rethink your algorithm and decide what you should be modifying (or if you need to make a copy of this box into another box, that you can modify).

  • break statement not within loop or switch
    You wrote break, but it is not inside of a loop (for, while, or do-while) nor a switch, so there is nothing to break out of. Often this error happens when curly braces do not match as you expect them to, thus what you expect to be inside a loop or switch is actually not.

  • both 'long' and 'short' in declaration specifiers
    You declared a variable with both long and short which does not make sense (e.g., you wrote long short int x;). Pick the one that you meant, and delete the other.

  • [C++] cannot dynamic_cast 'expr' (of type 'type1') to type 'type 2' (source type is not something)
    You can only use dynamic_cast to cast between pointers or references to class types that have at least one virtual function (and thus have a vtable in which to store the type information required to perform the runtime checks required by dynamic_cast). First, be sure your source type is a pointer or reference to a class type. If so, check if you have virtual functions in the base type. Remember that you should always have a virtual destructor for any type that you are using polymorphically.

  • [C++] cannot return from a handler of a function-try-block of a constructor
    If you write a function-try-block in a constructor to handle exceptions, the handlers may not return---they can only throw an exception (whether by implicitly rethrowing the original exception, or by explitly throwing a different exception). This requirement exists because an exception caught during the intializer list means the object could not be properly initialized, and thus is incomplete---it cannot be used, so the exception must propagate to wherever the object is being created. See Section 19.3.

  • comparison between signed and unsigned integer expressions
    A comparison (such as <, <=, etc.) is being made where one operand is a signed integer type and the other is an unsigned integer type. Comparing signed and unsigned values results in (typically) undesireable behavior due to the implicit conversion as discussed in Section 3.4.1.

  • continue statement not within a loop
    You wrote continue, but it is not inside of a loop (for, while, or do-while) so it does not make sense---there is no loop to go to the next iteration of. Often this error happens when curly braces do not match as you expect them to, thus what you expect to be inside a loop is actually not.

  • control reaches end of non-void function
    This error message means that the execution arrow can reach the close curly brace of a function (whose return type is something other than void) without encountering a return statement. This situation is problematic because the function has promised to return an answer, but can finish without saying what the answer is. Typically, the programmer has either forgotten to write a return statement at the end of the function, or has return statements inside of conditional statements where the compiler cannot convince itself that execution will encounter a return statement in all cases. Note that the compiler does not perform sophisticated algebraic reasoning about the relationships between the conditional expressions of if statements, so you may encounter this error in case where you can convince yourself that all cases are covered, but the compiler cannot. If this happens, add some code to print an error message and call abort(); to the end of the function, which will abort the program if the execution arrow reaches it (which would indicate your reasoning about the function was incorrect, and something needs to be fixed).

  • crosses initialization of 'type id'
    This is typically the second line of a multi-line error message, such as jump to case label crosses initialization of 'type id'. Look at the first line of the message, and find what to fix from that.

  • declaration for parameter 'id' but no such parameter
    This error message typically means that you forgot the open curly brace ({) at the start of the body of a function. The error message is phrased this way, as ancient versions of C declared parameters differently, and the first variable you declare inside the function that is missing its { appears to be from this style of parameter declaration.

  • [C++] duplicate base type 'id' invalid
    This error indicates that you tried to mutiply inherit from the same parent class multiple times. For example (where 'id' would be A): class B: public A, public A If you actually meant to try to multiply inherit from the same class multiple times, your inheritance hierarchy is likely quite flawed, and you should redesign it.

  • [C++] dynamic_cast of 'something' to 'otherthing' can never succeed
    You are trying to cast between types which are unrelated by inheritance, and therefore cannot possibly satisfy the runtime checks of dynamic_cast. You may want to read Section D.4.2 and Chapter 18, then rethink what you are doing. If you are sure you want to convert between unrelated types, you will need to use a different cast operator, however, odds are good that you will not like the results.

  • 'else' without a previous 'if'
    You have an else that does not come immediately after the ``then clause'' of an if. Often this error happens when your curly braces do not match as you expect them to.

  • expected '{' at end of input
    You are missing an open curly brace, and the compiler noticed this problem when it got to the end of your source code file.

  • fatal error: no input files
    You did not specify the .c (or .cpp) file(s) that you wanted to compile. It is also possible that the compiler does not think you specified an input file because you wrote the input file name in a position that is the argument of some other option. For example, if you wrote gcc -o myprogram.c, then gcc interprets myprogram.c as the argument to the option -o (i.e., the name of the output file to produce).

  • 'for' loop initial declaration used outside C99 mode
    Declaring a variable inside a for loop (for (int i = 0; ...) is a newer feature of C. Use --std=gnu99 in your compilation command line.

  • format not a string literal and no format arguments
    This error means that you have passed a format string (i.e., the first argument of printf or a similar function) as a variable (not a string literal) and it is the only argument to printf---that is, you wrote printf(str);. You should do printf("%s", str); instead. See Section 10.4 to understand why.

  • 'id1' is an inaccessible base of 'id2'
    This error means you are trying to use polymorphism with a class that inherited with non-public (protected or private) inheritance, in a circumstnace not permitted by the access modifier you used. For example, if you have the following two classes:
    class A {
      //...
    };
    class B : private A {
      //...
    };
    //...
    
    then you cannot use polymorphism to assign a B pointer (or reference) to an A pointer or reference, unless you are inside of the B class (or one of its friends). Most likely, you want to just use public inheritance, which will fix this problem.

  • 'id' redeclared as different kind of symbol
    This error means that you have redeclared the same variable (or function name) twice in incompatible ways. For example, if you write
      int myFunction(int x) {
         int x;
      ...
      ...
      }
    
    then you have two declarations of x---one as a parameter, and one as a local variable. If you actually want two different boxes, then give them different names. If you meant them to be the same, remove the extra declaration.

  • 'id' undeclared (first use in this function)
    The variable id has not been declared at this point in the code. The most likely reasons are:

    • You may have misspelled the variable's name (either at this point or when you declared it).

    • You forgot to declare the variable at all.

    • The variable's declaration was not in this scope.

    • The compiler was confused by another error when it was trying to process the declaration, so it skipped over it.
    Note that this is often followed by the messages (Each undeclared identifier is reported only once for each function it appears in.)
    which are not truly errors, but the compiler telling you that it will not report errors for future uses of this variable in the same function.

  • implicit declaration of function 'id'
    The compiler has found a call to a function which you have not declared (not provided a prototype for). If you encounter this error message for a function which is part of the C library (e.g., printf, strcmp, exit, etc.) it almost always means that you either forgot to #include the correct header (.h) file, or that you mis-spelled the function's name.

  • [C++]
    In constructor 'Something::Something(int, int)':
       'Something::z' will be initialized after
       'int Something::y'
       when initialized here
    
    The order that fields are initialized in your initializer list does not match the order in which they were declared in your class. This mismatch can result in problems as the fields are initialized by their declaration order, not the order that they appear in the initializer list. Please see Section 15.1.4 for more details.

  • initialization discards qualifiers from pointer target type
    See assignment discards qualifiers from pointer target type and note that this message only differs in that it appears when the assignment is the initialization of a variable in the same statement that the variable is declared in.

  • initialization makes integer from pointer without a cast
    See assignment makes integer from pointer without a cast and note that this message only differs in that it appears when the assignment is the initialization of a variable in the same statement that the variable is declared in.

  • initialization makes pointer from integer without a cast
    See assignment makes pointer from integer without a cast and note that this message only differs in that it appears when the assignment is the initialization of a variable in the same statement that the variable is declared in.

  • integer constant is too large for its type
    You wrote a constant that is too big for the type it is being used as. First, make sure there is a type for which you can write a literal constant that is compatible with the numeric value you wrote (they generally cannot be more than 64 bits for integers). If so, write the appropriate suffix on the constant (e.g., ULL for unsigned long long).

  • invalid digit "8" in octal constant
    invalid digit "9" in octal constant
    A number that starts with 0 (such as 0123) is an octal (base 8) constant. You cannot use 8 or 9 in such a constant.

  • invalid operands to binary op (have '+type1' and 'type2')
    You are trying to use a binary operator (op is something like +, -, *, /, %, ...) with types that are incompatible. For example,
      int * p = ...;
      float f = ...;
      p = p + f;  //error on this line
    
    Here, p is a pointer to an int, and f is a float. Trying to add them together is not permitted, since there is no meaningful interpretation of + when the operands are a pointer and float---you cannot perform pointer arithmetic in that way. Think through what you are trying to accomplish here, and what it is you want to add. If you are trying to add two structs, remember that it must be done element by element. Note that C++ will give you a slightly different error message, and has slightly different considerations.

  • [C++] invalid operands of types '+type1' and '+type2' to binary 'operator op'
    This error is very similar to the slightly different C error---which you should read. The major differerence when fixing this type of error in C++ is to consider operator overloading. It is possible that you may have tried to overload the operator in question for the types you wanted to use, but had some problem with that declaration. If so, you should find and fix the declaration of the overloaded operator you think should be used. If not, you may wish to fix this error by overloading the operator in question for those types, if that makes sense.

  • invalid suffix "X" on floating constant
    invalid suffix "X" on integer constant
    You wrote a constant with an invalid suffix letter, such as 3X or 4.2a. For integers, legal suffixes are typicall U (unsigned), L (long), LL (long long). The L and LL suffixed can be combined with U (UL or ULL). For floating point constants, the suffixed can typically be F (float), or L (long double). If you meant to write a hexadecimal (hex) integer, be sure to start it with 0x (such as 0x123A).

  • ISO C forbids empty initializer braces
    You wrote something like int x[6] = {};, presumably to try to initialize all elements of the array to 0. Technically, the C rules do not allow the empty braces (though many compilers will accept it). You should instead write int x[6]={0};

  • jump to case label case XX: crosses initialization of 'type id'
    You have a variable whose scope is the entire switch statement, but whose declaration and initialization appears inside one particular case. Either move the declaration outside of the switch statement, or wrap the case in {}s so that the scope of the variable is limited to that case.

  • large integer implicitly truncated to unsigned type
    You have a very large integer constant, which was not suffixed to indicate an unsigned type, but cannot fit into the signed type that the compiler tried to give it. First make sure that it can fit into a type which it is legal to write literal values for (typically at most 64-bits), then apply an appropriate suffix (e.g., ULL for unsigned long long) to the constant.

  • lvalue required as left operand of assignment
    lvalue is the technical term for ``something that names a box.'' If the left operand of an assignment (i.e., what is supposed to name the box you want to change) is not an lvalue---it does not name a box---then the assignment statement makes no sense. For example, if you write 3=4, you cannot change the value of 3 to be 4 (3 is not an lvalue: it does not name a box). This error can also come up when you write something like x+y=3. x+y does not name a box---it is an expression which evaluates to a value. Novice programmers often write something like this when they want x+y to be 3, but this is not specific enough. You need to explicitly say which variable to change and how to make this happen. For example, x=y-3 (if you want to change x) or y=x-3 (if you want to change y) might be two ways to accomplish this goal. You need to think about how you want to change things in a step-by-step fashion, and correct your code.

  • missing terminating " character
    You are missing the " character which ends a string literal, or it appears on the next line (you may not have a newline inside a string literal. If you want the string to contain a newline, use the \n escape sequence). You may have also forgotten to escape a " that you wanted to appear literally in the string (e.g., "Quotation marks look like \".").

  • no input files
    See fatal error: no input files.

  • old-style parameter declarations in prototyped function definition
    This error message typically means that you forgot the open curly brace ({) at the start of the body of a function. The error message is phrased this way, as ancient versions of C declared parameters differently, and the first variable you declare inside the function that is missing its { appears to be from this style of parameter declaration.

  • operation on 'id' may be undefined
    You have a statement which both uses and modifies 'id' in a way that is undefined. For example, if you write a[x++] = x; then it is undefined whether change to x caused by x++ happens before or after the value of \codeinline-x- is read to evaluate the expression on the right side of the statement. You should break your code down into multiple statements, each of which changes exactly one 'box'.

  • overflow in implicit constant conversion
    You are assigning a constant value to a variable whose type cannot hold the value that you wrote. The compiler is warning you that overflow (see Section 3.4.3) will occur in the assignment, and you will not actually end up with the variable holding the value that you wrote.

  • parameter 'id' is initialized
    This error message typically means that you forgot the open curly brace ({) at the start of the body of a function. The error message is phrased this way, as ancient versions of C declared parameters differently, and the first variable you declare and initialize inside the function that is missing its { appears to be from this style of parameter declaration.

  • [C++] request for member 'id' is ambiguous
    The compiler has multiple possible members (fields or methods) named 'id' that it could choose from here, and all are equally ``good,'' so it cannot decide. This error might occur if you are using multiple inheritance, and inherit from two classes with identically named members and then try to use that member in the child class (see Section 29.2.2).

  • return type of 'main' is not 'int'
    You have declared the main function with a return type other than int, which is not correct. The main function should always return an int, which should generally be either EXIT_SUCCESS or EXIT_FAILURE, as it indicates the success or failure status of the program.

  • stray '\' in program
    You have a \ somewhere in your program that does not belong.

  • stray '\##' in program (where ## is a number)
    You have an unusual character in your program. This error most often comes up when you copy from something that writes ``fancy'' quotation marks, and paste it into your editor.

  • suggest parentheses around assignment used as truth value [-Werror=parentheses]
    This error happens when you use an assignment (e.g., x=y) as a conditional expression---where the value of the assignment expression is evaluated for ``truth''. For example, if you write if(x=y) you will get this error. 99.99% of the time, what you meant is if(x==y) (with two equals signs, meaning to compare x and y for equality). The compiler messages ``suggests parenthesis'' because if you did mean to use the assignment expression as the conditional expression, you should write if( (x=y) != 0) (or if ( (x=y) != NULL)) to indicate that you explicitly meant to do this. `

  • templates may not be 'virtual'
    You cannot declared a templated method as virtual (though you can declare virtual methods inside a templated class). See Section 18.7.2 for more details, and Chapter 29 for an understanding of why.

  • too many decimal points in number
    You wrote a floating point literal with more than one decimal point, such as 3.4.5, which does not make sense. Correct the literal to the number that you intended.

  • type of 'id' defaults to 'int'
    You declared 'id' without a type, so the compiler assumed 'int'. This warning is most common if you declare a parameter without a type name, such as int f(x) {...}. The compiler assumes that x is an any, but gives you a warning since it is not sure that is what you meant.

  • [C++] uninitialized member 'ClassName::fieldName' with 'const' type 'const ty'
    Your class has a field (fieldName) which has a const type (which is either not a class, or is a POD type), which was not initialized in the class's initializer list. const fields must be initialized in the initializer list. If your class is a non-POD class, then a call to the default constructor will be automatically inserted, however, we recommend that you include an explicit initializer in the list anyways.

  • [C++] uninitialized reference member 'ClassName::fieldName'
    Your class has a field (fieldName) which has a reference type, but it was not initialized in the initializer list of one or more constructors. As references must be initialized, C++ requires that fields whose types are references be initialized in the initializer list. Assigning to them in the constructor is treated as a normal assignment (not an initialization), and is not sufficient to meet this requirement. See Section 15.1.4 for more details.

  • unterminated comment
    You have a comment started by /* with no matching */ to close it.

  • unused variable 'id'
    You have declared the specified variable, but have not used it anywhere in its scope (you may or may not have assigned to it, but have not read its value anywhere). The three most often causes of this error are (1) the variable is no longer needed---you have removed code that previously used it, but forgot to delete the declaration. In this case, just delete the declaration. (2) you may have mis-spelled the use(s) or it relative to the declaration (possibly meaning you mis-spelled the declaration, but spelled the uses correctly). This situation is often accompanied by error messages about undeclared variables, but may not be if you have closely named variables such that the mis-spellings appear correct (which is a bad idea---your variable names should ideally be rather different from each other within a scope). The solution here is to fix the spellings. (3) you may have two variables of the same name with overlapping scopes. In such a case, you may be referencing the wrong variable (the other one in scope with the same name) where you mean to use the one that is being noted as un-used. You can fix this problem by renaming your variables so they have unique names within a scope (which is a good idea anyways).