gpt4 book ai didi

没有malloc的完全封装

转载 作者:太空狗 更新时间:2023-10-29 17:11:51 24 4
gpt4 key购买 nike

我正在试验 C11 和 VLA,试图在堆栈上声明一个只有不完整声明的结构变量。目标是提供一种机制来创建某种结构类型的变量而不显示内部结构(如 PIMPL 习惯用法),但不需要在堆上创建变量并返回指向它的指针。此外,如果结构布局发生变化,我不想重新编译每个使用该结构的文件。

我已经成功编写了以下程序:

私有(private).h:

#ifndef PRIVATE_H_
#define PRIVATE_H_

typedef struct A{
int value;
}A;

#endif /* PRIVATE_H_ */

公共(public).h:

#ifndef PUBLIC_H_
#define PUBLIC_H_

typedef struct A A;

size_t A_getSizeOf(void);

void A_setValue(A * a, int value);

void A_printValue(A * a);

#endif /* PUBLIC_H_ */

实现.c:

#include "private.h"
#include "stdio.h"

size_t A_getSizeOf(void)
{
return sizeof(A);
}

void A_setValue(A * a, int value)
{
a->value = value;
}

void A_printValue(A * a)
{
printf("%d\n", a->value);
}

主.c:

#include <stdalign.h>
#include <stddef.h>

#include "public.h"

#define createOnStack(type, variable) \
alignas(max_align_t) char variable ## _stack[type ## _getSizeOf()]; \
type * variable = (type *)&variable ## _stack

int main(int argc, char *argv[]) {
createOnStack(A, var);

A_setValue(var, 5335);
A_printValue(var);
}

我已经测试了这段代码,它似乎可以工作。但是,我不确定我是否忽略了一些可能是危险的或不可移植的,或者可能会损害性能的东西(比如别名、对齐或类似的东西)。另外我想知道在 C 中是否有更好的(可移植的)解决方案来解决这个问题。

最佳答案

这当然违反了有效的类型规则(又名严格别名),因为 C 语言不允许类型 char [] 的对象通过不具有该类型的指针访问(或兼容的)。

可以通过-fno-strict-aliasing 等编译器标志或

等属性禁用严格别名分析
#ifdef __GNUC__
#define MAY_ALIAS __attribute__((__may_alias__))
#else
#define MAY_ALIAS
#endif

(感谢 R.. 指出后者),但即使您不这样做,在实践中,应该一切正常,只要您只能使用变量的专有名称来初始化类型化指针。

就个人而言,我会将您的声明简化为

#define stackbuffer(NAME, SIZE) \
_Alignas (max_align_t) char NAME[SIZE]

typedef struct Foo Foo;
extern const size_t SIZEOF_FOO;

stackbuffer(buffer, SIZEOF_FOO);
Foo *foo = (void *)buffer;

替代方法是使用非标准的 alloca(),但该“函数”有其自身的一系列问题。

关于没有malloc的完全封装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25538296/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com