代码之家  ›  专栏  ›  技术社区  ›  kamkow1

匿名结构的初始值设定项错误无效

  •  0
  • kamkow1  · 技术社区  · 12 月前

    我这里有这个代码:

    Void() aba ()
    {
    }
    #define std_Dynamic_Array(T) struct{Int32() count; Int32() capacity; T* memory; }
    Void() no_body_func (Int32() b);
    Int32() test_func (Int32()*** a)
    {
    }
    Int32() test_func2 (Int32() x)
    {
    }
    Int32() b = 33;
    #define v_macro(T) struct{Int32() count; Int32() capacity; T* memory; } v (std_Dynamic_Array(T)* m) \
    { \
        Int32() l = 44; \
    }
    Void() _main ()
    {
        Int64() a = 5;
        b = 22;
        Int32() c = test_func2(6);
        Int32() inner_func (Int32()* a)
        {
            Int32() g = 3;
        }
        Int32()* x = &b;
        inner_func(x);
        Int32() j = *x;
        Float32() f = 33.000000;
        std_Dynamic_Array(Int64()) da = {.count = 4};
        v_macro(Int64());
        std_Dynamic_Array(Int64()) k = v(&da);
    }
    
    int main(int argc, char ** argv)
    {
    
        return 0;
    }
    
    

    我正在努力编写自己的编译器,它可以生成C代码作为目标之一。我的问题是我得到了一个奇怪的错误:

    tests/simple.c:34:36: error: invalid initializer
       34 |     std_Dynamic_Array(Int64()) k = v(&da);
          |                                    ^
    

    这是由生成的代码 gcc -E ...

    void aba ()
    {
    }
    
    void no_body_func (int b);
    int test_func (int*** a)
    {
    }
    int test_func2 (int x)
    {
    }
    int b = 33;
    
    
    
    
    void _main ()
    {
        long long a = 5;
        b = 22;
        int c = test_func2(6);
        int inner_func (int* a)
        {
            int g = 3;
        }
        int* x = &b;
        inner_func(x);
        int j = *x;
        float f = 33.000000;
        struct{int count; int capacity; long long* memory; } da = {.count = 4};
        struct{int count; int capacity; long long* memory; } v (struct{int count; int capacity; long long* memory; }* m) { int l = 44; };
        struct{int count; int capacity; long long* memory; } k = v(&da);
    }
    
    int main(int argc, char ** argv)
    {
    
        return 0;
    }
    

    为什么会发生这种错误?二者都 v 的返回类型和 k 的类型扩展为 struct{int count; int capacity; long long* memory; } ,那么为什么GCC将它们视为不同的类型呢? 我能做些什么来解决这个问题? 而且

    1. 我不在乎代码的可读性,这是为GCC生成的代码,而不是供人类处理的。
    2. 如果解决方案需要人类和语言扩展所知的最巧妙的GCC技巧,那就顺其自然吧。C目标输出的代码将严格与GCC一起工作,无需担心clang、MSVC、ICC等。

    我知道我可能可以通过生成一些typedef来解决这个问题,但我想避免这种情况。至少现在是这样。

    谢谢

    1 回复  |  直到 12 月前
        1
  •  3
  •   Eric Postpischil    12 月前

    结构的每一个定义都会产生一个不同的类型,这是C的一个深思熟虑和可取的特征。如果我们有:

    typedef struct { double a, b; } GeometricPoint;
    typedef struct { double a, b; } ComplexNumber;
    

    那么我们想要 GeometricPoint ComplexNumber 可以是不同的类型,这样即使它们的布局相同,也不会意外地将其中一个指定给另一个。

    代码中的任何位置 struct{int count; int capacity; long long* memory; } ,您有一个不同的类型,并且这些类型中的每一个都与其他类型不兼容,因此,当尝试将一个类型分配给另一个类型、将一个作为另一个的参数传递时,或者尝试将指针分配给它们或传递参数时,都会收到警告和错误。

    要解决此问题,请使用标记声明该结构一次:

    struct MyStructure { int count; int capacity; long long *memory; };
    

    然后仅使用 struct 对于标签, struct MyStructure ,贯穿代码的其余部分。或者,您可以使用 typedef :

    typedef struct { int count; int capacity; long long *memory; } MyStructure;
    

    然后使用 类型定义 名称 MyStructure ,贯穿代码的其余部分。