【问题标题】:GCC reporting unrelated errors for includeGCC 报告包含的不相关错误
【发布时间】:2015-06-27 13:56:58
【问题描述】:

我已将新文件添加到项目中:

#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

如果存在include,我会在不相关的文件中获得大量error: expected ';', ',' or ')' before numeric constant。如果我删除include 并改用void * peer,一切都很好。 enet 库包含在其他地方的源文件中,并且工作正常。我正在使用 enet 1.3.13(最新),它的标头保护似乎就位。这是在 gcc 4.9.2 下。

记录在案错误发生在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

我确定这很简单——知道我做错了什么吗?

【问题讨论】:

    标签: c gcc compiler-errors enet


    【解决方案1】:

    一般来说,使用单字母宏名称是个好主意。它们可能很容易替换意外位置的字母(注意:宏实际上是在实际编译阶段之前的文本替换)。

    您写的错误是在 Point.h 中发生的。我不认为它们实际上发生,而只是报告。众所周知,C 很难检测到语法错误的实际位置。检查包含 Point.h 的文件

    注意:标题中的const struct Player playerEmpty; 也可能是不需要的,因为这将在每个编译单元中创建一个具有外部链接的对象。这与 C++ 不同:在 C 中,实际上没有常量,而只有 常量变量const 只是程序员的承诺,变量一旦初始化就永远不会改变。更糟糕的是:您没有为它分配一个值,从而使其有效0 - 全局变量被初始化为所有位 0。我很确定这不是故意的。

    更新:

    如果是积分的话,怎么样:

    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
    

    摆脱#defines 并获得正确的语法。

    注意__attribute__ ((__packed__)) 是特定于 gcc 的,以避免在结构字段之间填充字节。这是非标准的,但其他编译器通常具有类似的功能(例如pragma)。结构和数组的布局必须相同。

    这可能比索引更具可读性。请注意,匿名结构和联合字段是标准的。

    【讨论】:

    • 感谢 Olaf,re struct empties,注意 - 实际上目的是让它们为 0 - 它们被用作结构返回集合的失败值,或重置其他结构实例,其中有必要,无需设置零 - 我发现这更直观。
    • @ArcaneEngineer:请注意,这会在 C 中生成内存读取,因为它们不像 C++ 中的常量!在 C 语言中,使用#defines 会更好(并且通常的做法是使用 #defines,因为这样可以让编译器更好地优化。如果您仍然坚持使用变量,正确的方法是声明这个 static(尽管在一个标头),或者-正确的方法:在标头中有一个'extern'声明,在.c文件中具有实际定义。无论如何,我强烈建议显式初始化该值(大多数编译器抱怨缺少初始化器对于const 变量)。 ...
    • @ArcaneEngineer: ... - 来自一位经验丰富的长期 C(和其他语言)开发人员的善意提示。
    • 要点——我会尽快查看这些(以及你的 cmets,正确地),并解决,只是不是现在。
    • @ArcaneEngineer:好的。关于索引:您可能忽略了这就是我建立联合的原因。所以你可以同时使用:struct-notation 或 index。没关系!
    【解决方案2】:

    问题是单字符#defines。永远不要这样做。

    几个月来我一直在使用XYZ,但直到今天我加入Player.h 之前从未遇到过问题,这一定最终——以一种迂回的方式——引发了一些问题在预处理器/编译器中。将这些返回的编译移除到(表面上的)正常状态。

    感谢那些在 cmets 中提供帮助的人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-20
      • 1970-01-01
      • 1970-01-01
      • 2020-06-03
      • 2011-02-27
      • 1970-01-01
      • 2020-02-17
      • 2013-09-15
      相关资源
      最近更新 更多