我在一个文件中定义了一个类型.从该文件导出既复杂又凌乱.我想把它分配到别的地方.大体上是来自C++的PIMPL习惯用法,用C语言呈现.

我知道它的大小.因此,我可以malloc(size),C生命周期的神奇规则意味着void指针可以用作该类型的实例.但是我不想把它放在堆上.

在C++中,可以使用对齐存储和放置新项.在C中,没有新的位置.据我所知,没有办法在C语言的一些任意内存中开始一个生命周期.

因此,我刚刚写了这样一个可疑的概念:

extern void thing;
__asm__("\t.type thing,@object\n"
        ".pushsection .data\n"
        "\t.global thing\n"
        "\t.p2align 3\n"
        "thing:\n"
        "\t.zero 4032\n"
        "\t.size thing, 4032\n"
        ".popsection\n"
        );

就C中的意义而言,我并不是完全有信心.具体地说,我不能稍后将其写入头文件中,然后在源代码中定义同名的特定类型--编译器拒绝这种组合.另见Why does gcc allow extern declarations of type void (non-pointer)?

还能有比这更好的吗?我不关心人机工程学,我只关心C的类型别名规则是否能够在future 的编译器版本中揭露这种诡计并将其付之一炬.

就语言而言,正确的做法是放弃封装,将类型及其内部的所有乱七八糟的东西移到头中,但我不想这样做.我喜欢它的包装.

推荐答案

考虑所需大小的数组:

#include <stddef.h>

char _Alignas(max_align_t) Raw[N];

C 2018 6.5 7说允许的别名类型是:

…在其成员中包含上述类型之一的聚合或联合类型…

因此,您可以使用以下命令访问它:

union U
{
    struct MyStruct S;
    char _Alignas(max_align_t) Raw[N];
};

例如:

#include <stddef.h>
#include <stdio.h>

#define N   8

char _Alignas(max_align_t) Raw[N];

extern void foo(void *p);


int main(void)
{
    foo(Raw);
}


struct MyStruct
{
    int i;
    float f;
};

union U
{
    struct MyStruct S;
    char _Alignas(max_align_t) Raw[N];
};


void foo(void *p)
{
    union U *Up = p;
    Up->S.i = 3;
    Up->S.f = 4.5;
    printf("%d %g\n", Up->S.i, Up->S.f);
}

您还可以将您的类型定义为联合内部的匿名 struct ,使其看起来更像是直接 struct :

typedef union
{
    struct
    {
        int i;
        float f;
    };
    char _Alignas(max_align_t) Raw[N];
} MyType;


void foo(void *p)
{
    MyType *t = p;
    t->i = 3;
    t->f = 4.5;
    printf("%d %g\n", t->i, t->f);
}

C++相关问答推荐

初始化char数组-用于初始化数组的字符串是否除了存储数组的位置之外单独存储在内存中

如何将不同长度的位转换成字节数组?

如何使用低级C++写出数值

文件权限为0666,但即使以超级用户身份也无法打开

是否可以使用指针算法在不对齐的情况下在 struct 中相同类型的字段的连续序列之间移动?

如何在下面的C代码中正确管理内存?

如何确保在C程序中将包含uft8字符的字符串正确写入MySQL?

cairo 剪辑区域是否存在多个矩形?

如何用C语言为CLI应用程序编写按键检测系统?

链接到底是如何工作的,我在这里到底做错了什么

不同原型的危险C函数是可能的

-Wnonnull-Compare警告不是具有误导性吗?

如何将两个uint32_t值交织成一个uint64_t?

我正在try 将QSORT算法实现为C++中的泛型函数

为什么我的半数组测试和奇数组测试不起作用?(我使用Assert进行调试)

*S=0;正在优化中.可能是GCC 13号虫?或者是一些不明确的行为?

计算时出现奇怪的计算错误;N Select K;在C中

Ubuntu编译:C中的文件格式无法识别错误

Struct 内的数组赋值

#define X Defined(Y) 是有效的 C/C++ 宏定义吗?