Mab*_*bus 7 c pimpl-idiom c99 variable-length-array c11
我正在试验C11和VLA,试图在堆栈上声明一个只有不完整声明的结构变量.目标是提供一种机制来创建一些结构类型的变量而不显示内部(如PIMPL惯用法),但不需要在堆上创建变量并返回指向它的指针.此外,如果结构布局发生更改,我不想重新编译使用该结构的每个文件.
我设法编写了以下内容:
private.h:
#ifndef PRIVATE_H_
#define PRIVATE_H_
typedef struct A{
int value;
}A;
#endif /* PRIVATE_H_ */
Run Code Online (Sandbox Code Playgroud)
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_ */
Run Code Online (Sandbox Code Playgroud)
implementation.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);
}
Run Code Online (Sandbox Code Playgroud)
main.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);
}
Run Code Online (Sandbox Code Playgroud)
我已经测试了这个代码,它似乎工作.但是我不确定我是否会忽略某些可能危险或不可移植的东西(如锯齿,对齐或类似的东西),或者可能会损害性能.另外我想知道在C中是否有更好的(便携式)解决方案来解决这个问题.
这当然违反了有效类型规则(也称为严格别名),因为 C 语言不允许char []通过不具有该类型(或兼容类型)的指针来访问 tye 对象。
您可以通过编译器标志-fno-strict-aliasing或属性来禁用严格的别名分析
#ifdef __GNUC__
#define MAY_ALIAS __attribute__((__may_alias__))
#else
#define MAY_ALIAS
#endif
Run Code Online (Sandbox Code Playgroud)
(感谢 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;
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用非标准的alloca(),但该“功能”有其自身的一系列问题。
| 归档时间: |
|
| 查看次数: |
763 次 |
| 最近记录: |