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