灵活的阵列 - v困惑 [英] Flexible arrays - v confused

查看:71
本文介绍了灵活的阵列 - v困惑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为(正如他们在c99中那样)灵活的阵列出现了很多原因 - 但我也认为他们会很好地踩到

结构(比如说)在(比如)一个标题之后在内存中对齐

struct,例如:


struct element

{

int a;

int b;

};

typedef struct element elem;


struct header

{

int a;

elem element [];

};

typedef struct header head;

....


head * p;

....


(p - >元素)[10] = ...;


但是,如果标题包含这个


elem *元素,那么同样的''技巧''可以完成;

};


所以,我不能真正看到在这里使用空数组符号的好处。

无论如何,当它是一个
$时,你会如何为元素提供一些内存? b $ b数组类型 - 确定ly p - > element = malloc ...是一个错误,因为元素是

一个数组,所以不能分配给它?这让我想到了这样就可以让它像这样工作,也许你应该把一块内存,... / b $ b然后把地址转换成一个标题*,访问元素,然后索引

。但是再一次,你可以在元素声明中使用直接指针

表示法吗?


那么,我想,好吧,也许符号会允许我

初始化一个结构...

struct foo

{

int a ;

char b [];

};


struct foo s = {10,{''f'', ''o'',''o''}};


但是gcc并不喜欢(使用-std = c99),而且如果b是

声明为char * b,当然这是非法的......


struct foo s = {10,{" foo"}};


所以,我们开始说''它们必须是很好的,原因有很多''我现在好了。

完全混淆了灵活的数组可以为你做什么。可以

有人请帮帮我吗?


x


Jo

解决方案

#include< stdio.h>

#include< stdlib.h>


struct element

{

int a;

int b;

};

typedef struct element elem;


struct header

{

int a;

elem element [];

};


typedef struct header head;


int main(int argc,char * argv [])

{

head * p;

p = malloc(sizeof(struct header)+ sizeof(struct element) )* 10);

系统(PAUSE);

返回0;

}

这个声明一个类型为head的指针p

为一个struct头和10个元素分配内存

类型struct element。


Zero写道:

这个十二月lares一个类型为head的指针p
为一个struct头和10个元素分析内存类型struct element。




那是'很好,那又怎样? (见下文)。


Brian


-

请为上下文引用足够的上述消息。要从

Google执行此操作,请点击显示选项。并使用展开的

标题中显示的回复。


文章< 11 ************ *********@g47g2000cwa.googlegroups。 com>

< me ********* @ googlemail.com>写道:

我认为(因为他们在c99中)灵活阵列存在的原因很多......


它们确实存在只有一个原因:使旧的合法化

" struct hack" (正如常见问题解答中所述)。


要查看片刻,请查看struct hack。完成这样的事情:


#include< stdlib.h>


struct vector {

size_t N; / *向量中的值数* /

double val [1]; / *实际大小为n * /

};


struct vector * vec_new(size_t n){

struct vector * p ;


/ *这里需要n-1,因为数组有一个额外的元素* /

p = malloc(sizeof * p +(n?n - 1:0)* sizeof p-> val [0]);

if(p != NULL){

p-> n = n;

而(n)

p-> val [ - n ] = 0.0;

}

返回p;

}


void vec_free(struct vector) * p){

免费(p);

}


double vec_access(struct vector * p,size_t i){

if(i> = p-> n)

恐慌(" vec_access:不存在元素%lu \ n",(unsigned long)i);

返回p-> val [i];

}


使用C99灵活阵列结构成员,我们简单地删除

常数1。并删除从传递给malloc()的

计算中减去1的代码。这简化了vec_new:


p = malloc(sizeof * p + n * sizeof p-> val [0]);


等对生成的机器级代码没有影响,

除了它*必须*实际工作,而前C99版本

被允许生成行为不端的代码运行。 (也就是说,

结构黑客并非100%合法,尽管没有人生成它不起作用的机器的例子。)

但是,如果[具有
灵活数组成员的结构]包含[指针],则可以执行相同的技巧...


换句话说,我们可以同样写:


struct vector {

size_t n;

double * val;

};


struct vector * vec_new(size_t n){

struct vector * p;


p = malloc(sizeof * p);

if(p!= NULL){

p-> val = malloc(n * sizeof * p-> val);

if(p-> val!= NULL){

p-> n = n;

while(n)

p-> val [ - n] = 0.0;

}否则{

free(p);

p = NULL;

}

}

返回p;

}


void vec_free(struct vector * p){

free(p-> val); / *或者首先检查p!= NULL * /

免费(p);

}


其余的代码保持不变。

所以,我真的不能在这里看到使用空数组表示法的好处。


使用F.A.M.的优势(或结构黑客)是我们

避免第二个malloc()调用和相关的额外源代码,

和底层机器代码往往更有效率好吧

(虽然后者肯定不会承诺)。

无论如何,当它是一个
数组类型时,你如何为元素提供一些内存? ...


如上所示。

所以,我想,好吧,也许这个符号可以让我初始化一个结构。 ..


有一种方法来映射FAM或者修改实际的,
初始化实例。这至少是技术上不确定,但是,因为不能保证

不灵活的成员的支票。结构与柔性结构相匹配。结构。

struct foo
{
int a;
char b [];
};

struct foo s = {10,{''f'',''o'',''o''}};




你不能这样做;但是你可以这样做:


struct foo {

int a;

char b [];

};

struct foo_with_b_size_3 {

int a;

char b [3];

} s = {10,{''f'',''o'',''o''}};


struct foo * get_s(void){

return(struct foo *)& s;

}


这会遇到技术上不确定的情况。问题(虽然,再次,

似乎适用于所有实际的实现)。事实上它需要一个指针投射才有可能引起怀疑:任何代码需要指针投射的
可能是在冰上滑冰。

-

In-Real-Life:风河系统Chris Torek

美国犹他州盐湖城(40°39.22''N,111° 50.29''W)+1 801 277 2603

电子邮件:忘了它 http://web.torek.net/torek/index.html

由于垃圾邮件发送者,阅读电子邮件就像在垃圾中搜索食物一样。


I thought (as they''re in c99) that flexible arrays were there for a
number of reasons - but I also thought they''d be great for stepping
into structures (say) that were aligned in memory after (say) a header
struct, e.g.:

struct element
{
int a;
int b;
};
typedef struct element elem;

struct header
{
int a;
elem element[];
};
typedef struct header head;
....

head * p;
....

(p -> element)[10] = ...;

However, the same ''trick'' can be done if header contained this

elem * element;
};

So, I can''t really see the benefit of using empty array notation here.
And anyway, how would you malloc some memory for element when it''s an
array type - surely p -> element = malloc... is an error, as element is
an array, and so can''t be assigned to? That leaves me thinking that to
get it to work like that, maybe you should malloc a lump of memory,
then cast the address to a header *, access element, and then index
into that. But again, you could do this using straight forward pointer
notation in the declaration of element?

So, then I thought, well, maybe the notation would allow me to
initialise a struct ...

struct foo
{
int a;
char b[];
};

struct foo s = {10, {''f'', ''o'', ''o''}};

But gcc doesn''t like that (with -std=c99), and again, if b were
declared char * b, surely this is illegal ...

struct foo s = {10, {"foo"}};

So, Istarting from ''they must be great for a number of reasons'' I''m now
totally confused as to what flexible arrays can do for you. Could
someone please help me?

x

Jo

解决方案

#include <stdio.h>
#include <stdlib.h>

struct element
{
int a;
int b;
};

typedef struct element elem;

struct header
{
int a;
elem element[];
};

typedef struct header head;

int main(int argc, char *argv[])
{
head *p;
p = malloc ( sizeof(struct header) + sizeof(struct element) * 10);
system("PAUSE");
return 0;
}
This declares a pointer p of type head
which allocates memory for one struct header and 10 elements
of type struct element.


Zero wrote:

This declares a pointer p of type head
which allocates memory for one struct header and 10 elements
of type struct element.



That''s nice, so what? (See below).

Brian

--
Please quote enough of the previous message for context. To do so from
Google, click "show options" and use the Reply shown in the expanded
header.


In article <11*********************@g47g2000cwa.googlegroups. com>
<me*********@googlemail.com> wrote:

I thought (as they''re in c99) that flexible arrays were there for a
number of reasons ...
They really exist for just one reason: to legitimize the old
"struct hack" (as it is called in the FAQ).

To review for a moment, the "struct hack" is done something like this:

#include <stdlib.h>

struct vector {
size_t n; /* number of values in the vector */
double val[1]; /* actually size n */
};

struct vector *vec_new(size_t n) {
struct vector *p;

/* need n-1 here because the array has an "extra" element */
p = malloc(sizeof *p + (n ? n - 1 : 0) * sizeof p->val[0]);
if (p != NULL) {
p->n = n;
while (n)
p->val[--n] = 0.0;
}
return p;
}

void vec_free(struct vector *p) {
free(p);
}

double vec_access(struct vector *p, size_t i) {
if (i >= p->n)
panic("vec_access: nonexistent element %lu\n", (unsigned long)i);
return p->val[i];
}

To use a C99 "flexible array" structure member, we simply remove
the constant "1" and get rid of the code that subtracts 1 from the
computation passed to malloc(). This simplifies vec_new:

p = malloc(sizeof *p + n * sizeof p->val[0]);

and otherwise has no effect on the machine-level code produced,
except that it *must* actually work, whereas the pre-C99 version
was allowed to produce code that misbehaved at runtime. (That is,
the "struct hack" is not 100% legitimate, although no one has
produced examples of machines on which it does not work.)
However, the same ''trick'' can be done if [the struct that has the
Flexible Array Member] contained [a pointer] ...
In other words, we could equally write:

struct vector {
size_t n;
double *val;
};

struct vector *vec_new(size_t n) {
struct vector *p;

p = malloc(sizeof *p);
if (p != NULL) {
p->val = malloc(n * sizeof *p->val);
if (p->val != NULL) {
p->n = n;
while (n)
p->val[--n] = 0.0;
} else {
free(p);
p = NULL;
}
}
return p;
}

void vec_free(struct vector *p) {
free(p->val); /* or perhaps check p!=NULL first */
free(p);
}

The rest of the code remains unchanged.
So, I can''t really see the benefit of using empty array notation here.
The advantage to using the F.A.M. (or the struct hack) is that we
avoid the second malloc() call and the associated extra source code,
and the underlying machine code tends to be more efficient as well
(although the latter is certainly never promised).
And anyway, how would you malloc some memory for element when it''s an
array type ...
As shown above.
So, then I thought, well, maybe the notation would allow me to
initialise a struct ...
There is a way to map the F.A.M. or struct hack onto an actual,
initialized instance. This is at least "technically iffy", however,
as there is no guarantee that the offets of the members of the
"inflexible" structure match those of the "flexible" structure.
struct foo
{
int a;
char b[];
};

struct foo s = {10, {''f'', ''o'', ''o''}};



You cannot do this; but you can do:

struct foo {
int a;
char b[];
};
struct foo_with_b_size_3 {
int a;
char b[3];
} s = { 10, { ''f'', ''o'', ''o'' } };

struct foo *get_s(void) {
return (struct foo *)&s;
}

This runs into that "technically iffy" problem (although, again,
it seems to work on all real implementations). The fact that it
requires a pointer cast is reason enough to be suspicious: any code
that requires a pointer cast is probably skating on thin ice.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22''N, 111°50.29''W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.


这篇关于灵活的阵列 - v困惑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆