显然,具有灵活数组成员的结构不是要声明的,而是与指向该结构的指针一起使用.声明灵活的数组成员时,必须至少有一个其他成员,并且灵活数组成员必须是该结构中的最后一个成员.
假设我有一个看起来像这样的:
struct example{
int n;
int flm[];
}
Run Code Online (Sandbox Code Playgroud)
然后要使用它,我将必须声明一个指针并使用malloc为结构的内容保留内存.
struct example *ptr = malloc(sizeof(struct example) + 5*sizeof(int));
Run Code Online (Sandbox Code Playgroud)
也就是说,如果我希望我的flm []数组保持五个整数.然后,我可以像这样使用我的结构:
ptr->flm[0] = 1;
Run Code Online (Sandbox Code Playgroud)
我的问题是,我不应该只使用指针而不是这个吗?它不仅在C99之前兼容,而且我可以在有或没有指向该结构的指针的情况下使用它.考虑到我已经必须将malloc与flm一起使用,我不应该只能这样做吗?
考虑示例结构的这个新定义;
struct example{
int n;
int *notflm;
}
struct example test = {4, malloc(sizeof(int) * 5)};
Run Code Online (Sandbox Code Playgroud)
我甚至可以像柔性阵列成员一样使用替换:
这也有用吗?(如上面的示例定义为notflm)
struct example test;
test.n = 4;
notflm = malloc(sizeof(int) * 5);
Run Code Online (Sandbox Code Playgroud) 我有这个工作代码:
#import <stdlib.h>
#import <stdio.h>
typedef struct myarray {
int len;
void* items[];
} MYARRAY;
MYARRAY *collection;
void
mypop(void** val) {
puts(collection->items[collection->len]);
*val = collection->items[collection->len--];
}
void
mypush(void* val) {
int len = collection->len++;
collection->items[len] = val;
puts(collection->items[len]);
}
int
main() {
puts("Start");
collection = malloc( sizeof *collection + (sizeof collection->items[0] * 1000) );
collection->len = 0;
puts("Defined collection");
mypush("foo");
puts("Pushed foo");
mypush("bar");
puts("Pushed bar");
char str1;
mypop((void*)&str1);
puts("Popped bar");
puts(&str1);
char str2;
mypop((void*)&str2);
puts("Popped foo");
puts(&str2);
puts("Done");
return 0; …Run Code Online (Sandbox Code Playgroud) 具有灵活数组成员的结构是一种可以声明变量并sizeof可以应用变量的类型,这一事实会导致以下程序中出现异常行为。
文件fam1.c:
#include <stdio.h>\n#include <stddef.h>\n\nstruct s {\n char c;\n char t[]; };\n\nextern struct s x;\n\nsize_t s_of_x(void);\n\nint main(void) {\n printf("size of x: %zu\\n", sizeof x);\n printf("size of x: %zu\\n", s_of_x());\n}\nRun Code Online (Sandbox Code Playgroud)\n文件fam2.c:
#include <stddef.h>\n\nstruct s {\n char c;\n char t[2]; };\n\nstruct s x;\n\nsize_t s_of_x(void) {\n return sizeof x;\n}\nRun Code Online (Sandbox Code Playgroud)\n该程序在编译和运行时会发出一些令人惊讶的输出:
\n#include <stdio.h>\n#include <stddef.h>\n\nstruct s {\n char c;\n char t[]; };\n\nextern struct s x;\n\nsize_t s_of_x(void);\n\nint main(void) {\n printf("size of x: %zu\\n", sizeof …Run Code Online (Sandbox Code Playgroud) 在C中,代码
char *c = "Hello world!";
Run Code Online (Sandbox Code Playgroud)
存储Hello world!\0在rodata中,并c使用指向它的指针进行初始化。除了字符串以外,我该如何处理?
具体来说,我正在尝试定义自己的字符串类型
typedef struct {
size_t Length;
char Data[];
} PascalString;
Run Code Online (Sandbox Code Playgroud)
然后想要某种宏,以便我可以说
const PascalString *c2 = PASCAL_STRING_CONSTANT("Hello world!");
Run Code Online (Sandbox Code Playgroud)
并且具有相同的行为,即\x0c\0\0\0Hello world!存储在rodata中,并c2使用指向它的指针进行初始化。
我尝试使用
#define PASCAL_STRING_CONSTANT(c_string_constant) \
&((const PascalString) { \
.Length=sizeof(c_string_constant)-1, \
.Data=(c_string_constant), \
})
Run Code Online (Sandbox Code Playgroud)
正如这些 问题中所建议的那样,但它不起作用,因为它Data是一个灵活的数组:我收到了错误error: non-static initialization of a flexible array member(对于gcc,clang给出了类似的错误)。
这在C中可能吗?如果是这样,PASCAL_STRING_CONSTANT宏将是什么样?
澄清
对于C字符串,以下代码块永远不会将字符串存储在堆栈中:
#include <inttypes.h>
#include <stdio.h>
int main(void) {
const char *c = "Hello …Run Code Online (Sandbox Code Playgroud) 假设我们有一个以灵活数组成员结尾的结构:
struct foo {
size_t len;
uint8_t data[];
};
Run Code Online (Sandbox Code Playgroud)
如何在堆栈上分配这个结构(即内存在作用域结束时自动释放)?另外,如果len能包含字段的大小就更好了data。
目前,我做的事情如下:
uint8_t buf[256];
struct foo *foo = (struct foo *)buf;
foo->len = sizeof(buf) - sizeof(struct foo);
Run Code Online (Sandbox Code Playgroud)
然而,它很容易出错。使用alloca()可能会稍微好一点:
struct foo *foo = alloca(256 + sizeof(struct foo));
foo->len = 256;
Run Code Online (Sandbox Code Playgroud)
从那里,我可以定义一个像这样的宏:
#define STACK_ALLOC_FOO(SIZE) ({ \
struct foo *_tmp = alloca(SIZE + sizeof(struct foo)); \
_tmp->len = SIZE; \
_tmp; \
})
Run Code Online (Sandbox Code Playgroud)
并声明它:
struct foo *foo = STACK_ALLOC_FOO(256);
Run Code Online (Sandbox Code Playgroud)
但是,我不确定分配的内存的生命周期alloca()。是内部作用域还是函数?
另外,分配全局变量不起作用(即使这不是我主要关心的问题)。
有人有在堆栈上分配具有灵活数组成员的结构的良好实践吗?
这是C99代码:
typedef struct expr_t
{
int n_children;
foo data; // Maybe whatever type with unknown alignment
struct expr_t *children[];
} expr_t;
Run Code Online (Sandbox Code Playgroud)
现在,我该如何分配内存?
expr_t *e = malloc (sizeof (expr_t) + n * sizeof (expr_t *));
Run Code Online (Sandbox Code Playgroud)
要么
expr_t *e = malloc (offsetof (expr_t, children) + n * sizeof (expr_t *));
Run Code Online (Sandbox Code Playgroud)
?
被sizeof甚至保证与柔性阵列构件的工作类型(GCC接受它)?
在阅读了一些与柔性阵列成员相关的帖子后,我仍然不完全理解为什么我们需要这样的功能.
(如果我没有从上面可能的重复问题中解决我的问题,请怪我)
以下两个实现之间的真正区别是什么:
struct h1 {
size_t len;
unsigned char *data;
};
struct h2 {
size_t len;
unsigned char data[];
};
Run Code Online (Sandbox Code Playgroud)
我知道h2的大小就好像省略了灵活的数组成员(数据),即sizeof(h2) == sizeof(size_t).而且我也知道灵活的数组成员只能作为结构的最后一个元素出现,因此原始实现在位置上可以更灵活data.
我真正的问题是为什么C99添加此功能?仅仅因为sizeof(h2)不包含实际大小的数据?我相信我必须错过这个功能的一些更重要的观点.请指出给我.
我想在其中声明一个带有灵活数组成员的结构,然后使用sizeof()它.原型是:
typedef struct
{
uint16_t length;
uint8_t array[][2];
} FLEXIBLE_t;
Run Code Online (Sandbox Code Playgroud)
然后我宣布它:
const FLEXIBLE_t test = {
.length = sizeof(test),
.array = { { 0, 1 },
{ 2, 3 },
{ 4, 5 },
{ 6, 7 },
{ 8, 9 } }
};
Run Code Online (Sandbox Code Playgroud)
一切编译好的(GCC),但是当我审视test.length它的值是2,也就是说,它只是计数uint16_t的length本身.
如何在编译时计算结构的大小?似乎编译器使用原型而不是特定实例.
我试图将使用struct hack转换为使用灵活的数组成员,只是遇到以下错误消息:
错误:使用灵活数组成员的结构无效
(GCC 4.8.1,gnu99,MinGW)
在尝试追踪消息的原因之后,我将其提炼到以下相对最小的情况:
struct a {
union {
struct {
int b;
int c[];
} d;
} e;
};
Run Code Online (Sandbox Code Playgroud)
换句话说,具有灵活数组成员的结构看不到能够放入结构中的并集内,即使联合是结构的最后一个成员.
(请注意,将一个灵活的数组成员直接放在联合内部似乎确实有效.)
现在:除了恢复结构黑客(将c声明为长度为1的数组)之外,还有什么方法可以解决这个问题吗?指向联合内部结构的指针可以工作,但是会遇到额外的间接层.
特定
struct Foo {
uint32_t a;
uint32_t b[];
};
Run Code Online (Sandbox Code Playgroud)
什么是sizeof(Foo)?它是实现定义的还是未定义的行为?C vs C++的答案有何不同?