Search code examples
cgcccompiler-errorsenet

GCC reporting unrelated errors for include


I've added a new file to a project:

#ifndef PLAYER_H
#define PLAYER_H
#include "enet/enet.h" //the problem
typedef struct Player
{
    ENetPeer * peer; //requires problematic include
    //void * peer; //works, since no include required
} Player;
const struct Player playerEmpty;
#endif //PLAYER_H

If the include is present, I get reams of error: expected ';', ',' or ')' before numeric constant in unrelated files. If I remove the include and use void * peer instead, all is well. The enet library is included in a source file elsewhere, and works fine. I am using enet 1.3.13 (latest) and its header guards appear to be in place. This is under gcc 4.9.2.

For the record the errors are occurring in Point.h:

#ifndef POINT_H
#define POINT_H

#include <stdint.h>

#define X 0
#define Y 1
#define Z 2

typedef  int16_t  int16_Point2[2];
typedef  int32_t  int32_Point2[2];
typedef uint16_t uint16_Point2[2];
typedef uint32_t uint32_Point2[2];

typedef  int16_t  int16_Point3[3];
typedef  int32_t  int32_Point3[3];
typedef uint16_t uint16_Point3[3];
typedef uint32_t uint32_Point3[3];

#endif //POINT_H

I'm sure it's something simple - any idea what I am doing wrong?


Solution

  • Using single-letter macro names is a good idea in general. They might very easily replace the letters in unexpected locations (note: Macros are actually textual replacement before the actual compilation phases).

    You wrote the error is occuring in Point.h. I do not think they actually occur, but are only reported here. C is notoriously bad to detect grammar errors where they actually are. Check the file which includes Point.h

    Note: const struct Player playerEmpty; in a header is also likely unwanted, as that will create an object with external linkage in every compilation unit. This is different from C++: in C, there are actually no constants, but only constant variables: const is just a promise by the programmer the variable will never be changed once initialized. Even worse: you do not assign it a value, thus making it effectively 0 - global variables are initialized to all bits 0. I'm quite sure this in not intended.

    Update:

    If that is for points, how about:

    typedef union __attribute__ ((__packed__)) {
        struct {
            int16_t x,y,z;
        };    // anonymous union field (C99)
        int16_t vec[3];
    } int16_Point3;
    
    ...
    
    // usage:
    int16_Point3 point = (int16_Point3){ .x = 5, .y = 3 }; // compound literal
    point.z = point.x + point.vec[1]; // other word for point.y
    

    to get rid of the #defines and getting proper syntax.

    Note __attribute__ ((__packed__)) is gcc-specific to avoid padding bytes between struct fields. That is non-standard, but other compilers often have similar features (e.g. pragma). It is required to have identical layout for the struct and the array.

    That might be more readable than the indexing. Note that anonymous struct and union fields are standard.