'Too many initialisers'

Discussion in 'C Programming' started by BartC, Feb 15, 2014.

  1. BartC

    BartC Guest

    I get the error 'too many initialisers' with this code:

    int x;

    int main (void) {
    int table[]=
    {0,
    ((int)&x),
    ((int)&x),
    ((int)&x),
    ((int)&x),
    ((int)&x),
    ((int)&x),
    ((int)&x),
    ((int)&x),
    ((int)&x),
    ((int)&x)
    };
    }

    Is there something I'm doing wrong, or another compiler bug to be reported?
    (I've already found another - now confirmed - bug with another compiler
    earlier today; compiler bugs are supposed to be extremely rare.)

    The problem goes away if I have just one less item (the original code has
    272), or I replace &x with just x.

    Or if I just use a pointer array, which I think I'll use as a workaround.
    (This compiler is 64-bits so there would likely be issues with pointer
    truncation anyway, although the compiler didn't report this. I haven't used
    a pointer array already because the x's are really function pointers in the
    original code, and I would have to dig out CDECL to get it right.)

    (BTW I'm trying recompiling the same project with 4 or 5 different
    compilers. They all report different things as errors! How does anyone
    manage to write any sizeable C project and keep multiple compilers happy at
    the same time? They all have slightly different link requirements too!)
     
    BartC, Feb 15, 2014
    #1
    1. Advertisements

  2. BartC

    Eric Sosman Guest

    The only gotcha I see is the conversion of pointer to `int'.
    The result of converting a pointer to an integer is implementation-
    defined, and if the result is outside the range of `int' the
    behavior is undefined (6.3.2.3p6). So, the situation is a little
    bit peculiar: It's implementation-defined, but the implementation
    is allowed to "define" it as undefined behavior!

    Whether that has anything to do with the compiler's complaint
    is anybody's guess. The code is certainly not portable.
    ... so it seems quite likely that the converted pointers
    are outside the `int' range.
    There's an inherent ambiguity in figuring out "the" error
    in a piece of code. Fundamentally, all you can say is that the
    code doesn't parse, or violates some constraint or other, or even
    exceeds an implementation limit -- but pinpointing "the" point of
    departure is fuzzy. Given a faulty chunk of code X, there are many
    acceptable variants X1,X2,X3,... at greater or lesser edit distances
    from X. An error description like "missing comma" is really a diff
    of X and the compiler's choice of some Xn; a different compiler might
    choose Xm and report a different diff. Producing an error message
    that helps the programmer is at least as much art as science.
     
    Eric Sosman, Feb 15, 2014
    #2
    1. Advertisements

  3. BartC

    Lew Pitcher Guest

    One part of the answer it to stick as close as possible to the language
    standard, and not use language that results in "implementation-defined"
    or "undefined" behaviour.

    When you code, for instance, initializers to an integer table where the
    values of the initializers are pointers coerced into integer types, you
    take the risk of writing (or, if it passes compilation, using) code that
    does not do what you think it does. The language standard gives the
    compiler the "right" to complain about such code, and (in severe cases)
    call such code "an error".


    Such is the nature of compilers, and the execution environments in which
    they live. I would not, for instance, expect Microsoft Visual C++ (in C
    mode) to produce object or binary that can be /directly/ executed on a
    Risc-based Linux system, or a S370-based MVS system.
     
    Lew Pitcher, Feb 15, 2014
    #3
  4. I don't. I've tried both gcc and Microsoft's compiler, and your code
    compiles without error on both. On one system that has 32-bit int
    and 64-bit pointers, I get warnings:

    warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

    The casts are unsafe, and can lose information.

    You have more parentheses than you need; each occurence of `((int)&x)`
    could be `(int)&x`.

    Are you sure that you got that error with the *exact* code you posted?
    If not, please pocy-and-paste the actual code that produces the error.
    (Telling us what compiler you're using couldn't hurt.)
    Then dig out CDECL and get it right. I wouldn't waste time tracking
    down errors in code that you already know is wrong.
     
    Keith Thompson, Feb 16, 2014
    #4
  5. BartC

    Joe Pfeiffer Guest

    Why is using a pointer array a workaround? You want an array of
    pointers to ints; why aren't you simply declaring it that way?
     
    Joe Pfeiffer, Feb 16, 2014
    #5
  6. The simplest way to make function pointer types is to forget about the
    pointer -- at least at first. Just find a declaration of a typical
    function:

    int *some_function(const char *s, int **ipa);

    stick "typedef" in front and replace the function name with a name
    for the type. You can remove the parameter names if you like, just as
    you can in any function declaration:

    typedef int *opcode_func(const char *, int **);

    This defines a function type. You can make an array of function
    pointers using it just like you make an array if integer pointers from
    int:

    opcode_func *table[] = {...};

    This way you finesse the issue of where the *s and ()s go in the full
    type. You also get a shorthand for declaring (but not defining)
    functions that will go in the table:

    opcode_func add_func, sub_func, mul_func;

    <snip>
     
    Ben Bacarisse, Feb 16, 2014
    #6
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.