几个疑问(错误的行为或正确) [英] Few doubts (wrong behaviour or correct )

查看:62
本文介绍了几个疑问(错误的行为或正确)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



很多人在我的项目中使用过这段代码。它有效,因为b是

使用额外的内存用于其他4个变量。我访问obj [4] max。


这里有几个问题

1)哪里失败了。我的意思是有任何异常,它不会在假设malloc工作正常的情况下工作。


2)有人告诉我在C99我们有declar b obj [],这样它就可以在运行时声明为
。我们怎么做我们是否还要再次使用malloc。

这是否也有不良影响。


3)假设下面的代码是黑客并且它有效,我该怎么办?制作

适用于类型为a的n个对象,每个对象都有类型为b的k个对象。


4)是b * ptr而不是b obj [ 1]更好的方法。为什么要使用b

obj [1]而不是b * ptr。


#include< stdio.h>

#include< stdlib.h>

typedef struct b {

int b1;

char bc;

} b;


typedef struct a {

char a;

int a1;

b obj [ 1];

} a;


a * ptr;

int main()

{


ptr = malloc(sizeof(struct a)+(sizeof(struct b)* 5));


返回0;

}

Hi,
Many people have used this code in my project. It works because b is
using the extra memory for other 4 variables.I access obj[4] max.

well here are a few questions
1) Where does it fail. I mean is there any exception where it willnot
work assuming malloc works fine.

2) someone told me in C99 we have declar b obj[] , so that it can be
declared at runtime. How do we do that. Do we have to malloc again .
Does this also have unwanted effects.

3)Assuming the below code is a hack and it works , how do i make it
work for n objects of type a with each a having k objects of type b.

4) is b *ptr instead of b obj[1] a better way. Why should one use b
obj[1] instead of b *ptr.

#include<stdio.h>
#include<stdlib.h>
typedef struct b{
int b1;
char bc;
}b ;

typedef struct a{
char a;
int a1;
b obj[1];
}a;

a *ptr;
int main()
{

ptr=malloc(sizeof(struct a ) + (sizeof(struct b)*5));

return 0;
}

推荐答案



2006年10月11日星期三 te ******** @ gmail.com 写道:

>
>



(我清理了你的代码。我希望你不要在现实生活中编写类似的代码

。)

(I cleaned up your code a bit. I hope you don''t write code like that
in Real Life.)


#include< stdio.h>

#include< stdlib.h>

typedef struct b {

int b1;

char bc;

} b;


typedef struct a {

char a;

int a1;

b obj [1];

} a;


int main()

{

a * ptr;

ptr = malloc(sizeof(struct a)+ 5 * sizeof(struct b));
#include <stdio.h>
#include <stdlib.h>
typedef struct b {
int b1;
char bc;
} b;

typedef struct a {
char a;
int a1;
b obj[1];
} a;

int main()
{
a *ptr;
ptr = malloc(sizeof(struct a) + 5*sizeof(struct b));



[...]

[...]


返回0;

}


这里有几个问题

1)哪里失败了。我的意思是,有任何例外情况,假设malloc工作正常,它将无法工作。
return 0;
}

well here are a few questions
1) Where does it fail. I mean is there any exception where it willnot
work assuming malloc works fine.



从技术上讲,它不必按照任何标准工作,因为

你将访问数组'' b''超越它的结束。 (''b''有一个元素,

根据它的定义,所以访问''b [1]''是一个错误。)


在实践中,这在历史上是如何在Unix中实现很多东西的b $ b等等,所以很多编译器都会尽力确保

它的运行方式你期望的。

Technically, it doesn''t have to work according to any standard, because
you''ll be accessing the array ''b'' beyond its end. (''b'' has one element,
according to its definition, so accessing ''b[1]'' is an error.)

In practice, this is historically how a lot of things were implemented
in Unix and so on, so many compilers go out of their way to make sure
it works the way you expected.


2)有人告诉我在C99我们有声明b obj [],所以它可以是

在运行时声明。我们怎么做我们是否还要再次使用malloc。

这是否也会产生不良影响。
2) someone told me in C99 we have declar b obj[] , so that it can be
declared at runtime. How do we do that. Do we have to malloc again .
Does this also have unwanted effects.



参见 http://david.tribble.com/text/cdiffs.htm#C99-fam

你会写下你已经拥有的东西,除了你的写''b []''

而不是''b [1]''。由于''b''现在不再只有一个元素,根据C99标准,它可以接受b [0],b [1],b [2] ],

等等。

唯一的不良影响这种方法---它是一个很大的问题---

是它不能用于C99之前的C编译器。

See http://david.tribble.com/text/cdiffs.htm#C99-fam
You''d write exactly what you already have, except you''d write ''b[]''
instead of ''b[1]''. Since ''b'' now no longer has only one element, it''s
acceptable, according to the C99 standard, to refer to b[0], b[1], b[2],
and so on.
The only "unwanted effect" of this approach --- and it''s a big one ---
is that it won''t work on pre-C99 C compilers.


3)假设下面的代码是hack并且它有效,我该如何使用

适用于类型为a的n个对象,每个对象具有b类型的k对象。
3) Assuming the below code is a hack and it works , how do i make it
work for n objects of type a with each a having k objects of type b.



你不是。你重写代码使用一个指向单独的/ b $ b malloc''数组的指针,这是/真正的/便携式解决方案---它在C90和C90中都可以工作
C99。

You don''t. You rewrite the code to use a pointer to a separately
malloc''ed array, which is the /real/ portable solution --- it works
in both C90 and C99.


4)是b * ptr而不是b obj [1]更好的方法。为什么要使用b

obj [1]而不是b * ptr。
4) is b *ptr instead of b obj[1] a better way. Why should one use b
obj[1] instead of b *ptr.



这是一种更好的方式。 结构黑客是指结构黑客。这是一个历史上的奇怪,但是为了使用它你不应该在新代码中使用它。使用

正确,便携的方法,即使它还需要两行。


struct a {

char a;

int a1;

b * obj;

};


int main()

{

struct a * ptr = malloc(sizeof * ptr);

if(ptr!= NULL)

ptr - > obj = malloc(6 * sizeof * ptr-> obj);

[...]

免费(ptr-> obj);

免费(ptr);

返回0;

}


HTH,

-Arthur

It is a better way. The "struct hack" is a historical oddity, but
you shouldn''t use it in new code just for the sake of using it. Use
the correct, portable method, even if it takes two more lines.

struct a {
char a;
int a1;
b *obj;
};

int main()
{
struct a *ptr = malloc(sizeof *ptr);
if (ptr != NULL)
ptr->obj = malloc(6*sizeof *ptr->obj);
[...]
free(ptr->obj);
free(ptr);
return 0;
}

HTH,
-Arthur


Arthur J. O''Dwyer写道:
Arthur J. O''Dwyer wrote:

>这里有几个问题
1)它在哪里失败。我的意思是,如果假设malloc工作正常,它会不会有任何异常。
>well here are a few questions
1) Where does it fail. I mean is there any exception where it willnot
work assuming malloc works fine.



从技术上讲,它不必按照任何标准工作,因为

你将访问数组'' b''超越它的结束。 (''b''有一个元素,

根据其定义,所以访问''b [1]''是一个错误。)


Technically, it doesn''t have to work according to any standard, because
you''ll be accessing the array ''b'' beyond its end. (''b'' has one element,
according to its definition, so accessing ''b[1]'' is an error.)



(你可能的意思是数组obj。'''b''是类型。''obj''是数组名称。)


你在说什么事实并非如此。


标准中没有任何内容表明你所讨论的局限性特别适用于数组''obj''因为它被宣布为

(即具有声明中指定的大小)。注意,当我们使用''[]''运算符时,数组类型会立即衰减到指针类型,

意味着''obj [1]''是相当于''*((b *)obj + 1)'',即

''obj''值不再是数组,而只是指针。我们走多远

允许离开那个指针只取决于腐朽的''obj'指向的
_actual_数组的大小,而不是声明的大小

数组''obj''。实际大小是由一个且只有一个定义的 - 我们实际为结构分配了多少内存。


错误的假设struct hack ; (非零数组大小)

以某种方式非法通常是两个流行错误之一的后果:


1)人们误认为它是零大小struct hack (这确实是一个

hack并且确实是非法的)


2)人们习惯于在大多数实际情况下实际的

C中数组的大小与其声明的大小相同。在这种情况下,

访问超出声明的大小确实是非法的。但是,struct

hack是一个完全不同的野兽。

(You probably meant "array obj". ''b'' is the type. ''obj'' is the arrays name.)

What you are saying is not true.

There''s nothing in the standard that says that the limitation you are
talking about applies specifically to array ''obj'' as it is declared
(i.e. with the size specified in the declaration). Note, that when we
use the ''[]'' operator, array type immediately decays to pointer type,
meaning that ''obj[1]'' is equivalent to ''*((b*) obj + 1)'', i.e. where
''obj'' value is no longer an array, but a mere pointer. How far we are
allowed to step away from that pointer depends only on the size of the
_actual_ array pointed by decayed ''obj'', not by the declared size of
array ''obj''. That actual size is defined by one and only one thing - how
much memory we actually allocated for the struct.

The incorrect assumption that "struct hack" (with nonzero array size) is
somehow illegal is normally a consequence of one of two popular mistakes:

1) People mistake it with a zero-size "struct hack" (which is indeed a
"hack" and is indeed illegal)

2) People are used to the fact that in most practical cases the actual
size of the array in C is identical to its declared size. In such cases
access beyond the declared size is indeed illegal. However, "struct
hack" is a completely different beast.


在实践中,这在历史上是如何在Unix中实现很多东西

等等,所以许多编译器都会尽力确保

它按预期方式工作。
In practice, this is historically how a lot of things were implemented
in Unix and so on, so many compilers go out of their way to make sure
it works the way you expected.



具体是指在声明中使用零大小的数组。

这将是非法的。而这正是许多编制者走出去的时候。允许作为扩展。


至于具有非零大小数组的结构黑客(如在OP的例子中)

那里''没有什么是非法的,绝对没有额外的努力

编译器需要支持它。

That specifically refers to using a zero-sized array in the declaration.
That would be illegal. And that''s exactly what many compilers "went out
of their way" to allow as an extension.

As for the struct hack with non-zero-sized array (as in OP''s example)
there''s nothing illegal about it and absolutely no additional effort is
required from the compiler in order to support it.


> 4)是b * ptr而不是b obj [1]更好的方法。为什么要使用b
obj [1]而不是b * ptr。
>4) is b *ptr instead of b obj[1] a better way. Why should one use b
obj[1] instead of b *ptr.



这是一种更好的方式。 结构黑客是指结构黑客。这是一个历史上的奇怪,但是为了使用它你不应该在新代码中使用它。


It is a better way. The "struct hack" is a historical oddity, but
you shouldn''t use it in new code just for the sake of using it.



绝对不是。对于一个很难理解

" struct hack"的初学者这可能是一个很好的临时技术。然而,它是以不必要的间接级别为代价的,这是一个设计问题和性能问题:需要深层复制,间接访问
需要
,内存碎片增加,访问位置减少

等。在成熟代码中struct hack当变量大小的数组是结构的自然聚合成员(根据程序的设计)时,技术是进入

情况的正确方法。


-

祝你好运,

Andrey Tarasevich

Absolutely not. For a beginner who has hard time understanding the
"struct hack" this might be a good temporary technique. However, it
comes at the cost of unnecessary level of indirection, which is a design
issue and a performance issue: deep-copy required, indirect access
required, memory fragmentation increased, locality of the access reduced
etc. In mature code "struct hack" technique is the correct way to go in
situations when the variable-size array is a natural aggregate member of
the struct (according to the program''s design).

--
Best regards,
Andrey Tarasevich

Andrey Tarasevich< an ************** @ hotmail.comwrites:

[...]
Andrey Tarasevich <an**************@hotmail.comwrites:
[...]

至于具有非零大小数组的结构hack(如在OP的例子中)

那里没有任何违法行为,绝对没有额外的努力是

需要编译器才能支持它。
As for the struct hack with non-zero-sized array (as in OP''s example)
there''s nothing illegal about it and absolutely no additional effort is
required from the compiler in order to support it.



确实不需要额外的工作来支持结构

hack,至少对于大多数编译器而言。但是如果一个编译器去实现数组边界检查需要额外的努力,那么就可以使用struct hack打破代码。


例如:


int arr [5];

arr [5] = 42;


在大多数实现中,编译器不会抱怨这个,并且

程序很乐意将值42写入一些内存。

但它'未定义的行为,这意味着编译器*允许*做任何它喜欢的事情,包括捕获错误。


-

Keith Thompson(The_Other_Keith) ks***@mib.org < http://www.ghoti.net/ ~kst>

圣地亚哥超级计算机中心< *< http://users.sdsc.edu/~kst>

我们必须做点什么。这是事情。因此,我们必须这样做。

It''s true that no additional effort is required to support the struct
hack, at least for most compilers. But if a compiler goes to the
consdeirable extra effort to implement array bounds checking, it could
break code that uses the struct hack.

For example:

int arr[5];
arr[5] = 42;

In most implementations, the compiler won''t complain about this, and
the program will happily write the value 42 over some chunk of memory.
But it''s undefined behavior, which means a compiler is *allowed* to do
anything it likes, including catching the error.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.


这篇关于几个疑问(错误的行为或正确)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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