工会Redux [英] Unions Redux

查看:41
本文介绍了工会Redux的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,我们最近有两个关于工会的漫长而偶然的线索,

我仍​​然觉得不太接近确定允许的内容

什么都不是。其他主题话题是Real Life Unions

和union {unsigned char u [10]; ...}"。


这是一个具体的例子:


#include< stdio.h>


int main(无效)

{

union {int s;我们没有签名; } u;


u.us = 50;

printf("%d \ nn",us);

返回0;

}


这个程序定义明确(打印50),实现定义,还是

UB ?


请注意,这里没有违反C99 6.5中的别名规则 - 在该部分下不禁止
访问某些类型的对象T
带有左值表达式的
,其类型是T的有符号或无符号

版本。


换句话说,有没有什么

限制''免费'使用工会的别名规则除外?

Ok, we''ve had two long and haphazard threads about unions recently,
and I still don''t feel any closer to certainty about what is permitted
and what isn''t. The other thread topics were "Real Life Unions"
and "union {unsigned char u[10]; ...} ".

Here''s a concrete example:

#include <stdio.h>

int main(void)
{
union { int s; unsigned int us; } u;

u.us = 50;
printf("%d\n", u.s);
return 0;
}

Is this program well-defined (printing 50), implementation-defined, or
UB ?

Note that the aliasing rules in C99 6.5 are not violated here -- it is
not forbidden under that section to access an object of some type T
with an lvalue expression whose type is the signed or unsigned
version of T.

In other words, is there anything other than the aliasing rules that
restrict ''free'' use of unions?

推荐答案

旧Wolf< ol ***** @ inspire.net.nzwrote:
Old Wolf <ol*****@inspire.net.nzwrote:

[snip]

union {int s;我们没有签名; } u;

u.us = 50;

printf("%d \ n",u.s);
[ snip ]
union { int s; unsigned int us; } u;
u.us = 50;
printf("%d\n", u.s);



我在看N1124。附件J列出了未指明的

行为,


- 工会成员的价值不是最后一个存储的

进入(6.2.6.1)。


附件J是提供信息的,不是规范性的,但是仍然有意义

请参阅第6.2.6.1节以了解原因行为未指定。

我们看到us和u.us有对象表示作为
unsigned char序列(第2,4段),但有些对象<当你访问我们时,
表示可能是陷阱表示导致未定义的

行为(参数5)。再深一点,6.2.6.2(1-2)

保留int有更多陷阱表示的可能性

比unsigned int,例如,如果有填充位或如果ints

是符号幅度,6.2.6.2(2)中的M

因此,您的代码似乎未定义(不仅仅是未指定的)

行为,按6.2.6.1(5)。


如果你想把你的50读作有符号的int,你需要转换通过赋值,u.s = u.us;在一台非常邪恶的机器上,

这项任务不一定是无操作!


我的论点不是另一种方式。 6.2.6.2(5)说:


有符号整数的有效(非陷阱)对象表示

类型,其中符号位为零是一个有效的对象表示
对应的无符号类型的
,并且代表

相同的值。


所以我没有排除

us = 50;

printf("%u \ nn",u.us);


我无法在6.2.6.1中看到任何可以排除其他内容的东西。

第6.2.6.1(7)段适用,但我很确定sizeof(int)= =

sizeof(unsigned int)乘6.2.6.2所以没有剩余的字节

for(7)to ... bite(D''oh)。

I was looking at N1124. Annex J lists among the unspecified
behaviors,

-- The value of a union member other than the last one stored
into (6.2.6.1).

Annex J is informative, not normative, but it still makes sense to
look at section 6.2.6.1 to see why the behavior is unspecified.
There we see that u.s and u.us have object representations as
sequences of unsigned char (paragraphs 2,4), but that some object
representations may be trap representations leading to undefined
behavior when you access u.s (par. 5). Further down, 6.2.6.2(1-2)
leave open the possibility that int has more trap representations
than unsigned int, for example if there are padding bits or if ints
are sign-magnitude and M<N-1 in 6.2.6.2(2).

So it seems that your code has undefined (not just unspecified)
behavior, by 6.2.6.1(5).

If you want to read your 50 as a signed int, you need to convert
the bits, e.g. by assignment, u.s= u.us; on a really wicked machine,
that assignment need not be a no-op !

My argument doesn''t work the other way. 6.2.6.2(5) says:

A valid (non-trap) object representation of a signed integer
type where the sign bit is zero is a valid object representation
of the corresponding unsigned type, and shall represent
the same value.

so I haven''t ruled out
u.s = 50;
printf("%u\n", u.us);

I can''t see anything else in 6.2.6.1 that could rule it out, either.
Paragraph 6.2.6.1(7) applies, but I''m pretty sure that sizeof(int)==
sizeof(unsigned int) by 6.2.6.2 so there are no leftover bytes
for (7) to ... bite (D''oh).


请注意,这里没有违反C99 6.5中的别名规则 - 在该部分下禁止访问的是
某种类型的对象T

,带有左值表达式,其类型为有符号或无符号

版本的T.
Note that the aliasing rules in C99 6.5 are not violated here -- it is
not forbidden under that section to access an object of some type T
with an lvalue expression whose type is the signed or unsigned
version of T.



我不认为这是相关的。它说,为了优化的目的,编译器必须假定
假定u.s和u.us可能是别名(好吧,duh)。例如,


memcpy(buf,& u.us,sizeof(u.us)); / * unsigned char buf [BIG] * /

do_something((const unsigned char *)buf);

us = 50;

memcpy (buf,& u.us,sizeof(u.us)); / *不能优化* /

I don''t think that''s relevant. It says that the compiler must
assume, for optimization purposes, that u.s and u.us are potentially
aliased (well, duh). For example,

memcpy(buf, &u.us, sizeof(u.us)); /* unsigned char buf[BIG] */
do_something((const unsigned char *)buf);
u.s= 50;
memcpy(buf, &u.us, sizeof(u.us)); /* can''t optimize out */


换句话说,除了别名规则之外还有其他什么吗?

限制免费使用工会?
In other words, is there anything other than the aliasing rules that
restrict ''free'' use of unions?



正如我所说,我不认为别名规则很重要。你的例子

相当于一个C ++ reinterpret_cast< intand可以打一个陷阱

表示。

-

pa at panix dot com

As I said, I don''t think the aliasing rules matter. Your example
amounts to a C++ reinterpret_cast<intand can hit a trap
representation.
--
pa at panix dot com


2007年3月14日15:10:44 -0700,老狼 < ol ***** @ inspire.net.nz>

在comp.lang.c中写道:
On 14 Mar 2007 15:10:44 -0700, "Old Wolf" <ol*****@inspire.net.nz>
wrote in comp.lang.c:

好​​的,我们最近有两个关于工会的漫长而随意的线索,

我仍​​然觉得不太接近确定允许的内容

和什么不是''吨。其他主题话题是Real Life Unions

和union {unsigned char u [10]; ......}
Ok, we''ve had two long and haphazard threads about unions recently,
and I still don''t feel any closer to certainty about what is permitted
and what isn''t. The other thread topics were "Real Life Unions"
and "union {unsigned char u[10]; ...} ".



大部分的漫游都是由原来的OP造成的,我认为比原材料更贵。我不批评,只是观察。

Most of the rambling was caused by the original OP, I think, rather
than the material. I am not criticizing, just observing.


这里有一个具体的例子:


#include< stdio.h> ;


int main(无效)

{

union {int s;我们没有签名; } u;


u.us = 50;

printf("%d \ nn",us);

返回0;

}


这个程序定义明确(打印50),实现定义,还是

UB ?
Here''s a concrete example:

#include <stdio.h>

int main(void)
{
union { int s; unsigned int us; } u;

u.us = 50;
printf("%d\n", u.s);
return 0;
}

Is this program well-defined (printing 50), implementation-defined, or
UB ?



程序定义明确,我会进一步详细说明。

The program is well-defined, I''ll elaborate further down.


注意这里没有违反C99 6.5中的别名规则 - 在该部分下不禁止
访问某种类型的对象T

,其中左值表达式的类型为已签名或未签名

版本的T.
Note that the aliasing rules in C99 6.5 are not violated here -- it is
not forbidden under that section to access an object of some type T
with an lvalue expression whose type is the signed or unsigned
version of T.



正如您所指出的,它不违反别名规则,但有

其他要考虑的规则。在这种特殊情况下,您正在访问

类型为unsigned int的对象,其左值表达式为

signed int。操作有效性的整个问题

取决于对象表示的兼容性,并且没有什么与

有关,这与涉及联合的事实有关。 br />

在这种特殊情况下,操作是明确定义的,因为

标准'对相应的有符号和无符号整数的保证

类型。对于两种类型范围内的正值,两者的位

表示相同。


但是,如果您已将INT_MAX + 1分配给u .us,你的

实现是UINT_MAX INT_MAX,

行为将被实现定义的通用实现之一,因为,至少

理论上,(无符号)INT_MAX + 1可以包含一个位模式,

是signed int的陷阱表示。

As you pointed out, it does not violate the alias rules, but there are
other rules to consider. In this particular case, you are accessing
an object of type unsigned int with an lvalue expression of type
signed int. The entire question of the validity of the operation
depends on the object representation compatibility, and has nothing at
all to do with the fact that there is a union involved.

In this particular case, the operation is well-defined because of the
standard''s guarantees about corresponding signed and unsigned integer
types. For a positive value within the range of both types, the bit
representation is identical for both.

However, if you had assigned INT_MAX + 1 to u.us, and your
implementation is one of the universal ones where UINT_MAX INT_MAX,
the behavior would be implementation-defined because, at least
theoretically, (unsigned)INT_MAX + 1 could contain a bit pattern that
is a trap representation for signed int.


换句话说除了别名规则之外还有什么可以限制免费使用工会吗?
In other words, is there anything other than the aliasing rules that
restrict ''free'' use of unions?



就个人而言,我认为人们可以在神秘而神奇的工会中获得工资。


它们适用于两件事:


1.节省空间,例如包含数据类型说明符的结构

和所有的联合可能的数据类型。这是消息传递系统中常见的

功能。一般来说,在这里使用的类型为双打不是



2.另一种打字方式。


考虑:


int test_lone(long l)

{

int * ip =(int *)& l;

int i = * ip;

返回i == l;

}


这是代码是未定义的,实现定义的还是未指定的?


从技术上来说它是未定义的,但是在像今天这样的实现上是典型的桌面,其中int和long具有相同的表示和

对齐,结果将是函数返回1.在

实现中int和long是不同的大小,谁知道。


现在考虑:


int test_long(长l)

{

union {长ll; int ii} li;

li.ll = l;

return li.ll == li.ii;

}


此代码是否未定义?嗯,是的,但与第一个函数相比,

功能没有什么不同。如果int和long具有相同的

表示,它将返回1.


联合中的别名与通过

指针投射。


-

Jack Klein

主页: http://JK-Technology.Com



comp的常见问题解答.lang.c http://c-faq.com/

comp.lang.c ++ http://www.parashift.com / c ++ - faq-lite /

alt.comp.lang.learn.c-c ++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html

Personally, I think people get to wound up in the mystical and magical
properties of unions.

They are good for two things:

1. Space saving, such as a struct containing a data type specifier
and a union of all the possible data types. This is a frequent
feature in message passing systems. Generally, type punning is not
used here.

2. Another way to do type punning.

Consider:

int test_lone(long l)
{
int *ip = (int *)&l;
int i = *ip;
return i==l;
}

Is this code undefined, implementation-defined, or unspecified?

Technically it is undefined, but on an implementation like today''s
typical desktop, where int and long have the same representation and
alignment, the result will be that the function returns 1. On an
implementation where int and long are different sizes, who knows.

Now consider:

int test_long(long l)
{
union { long ll; int ii } li;
li.ll = l;
return li.ll==li.ii;
}

Is this code undefined? Well, yes, but it is no different in
functionality than the first function. If int and long have the same
representation, it will return 1.

There is no difference in aliasing in a union than there is via
pointer casting.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html


3月14日下午6:10,老狼 < oldw ... @ inspire.net.nzwrote:
On Mar 14, 6:10 pm, "Old Wolf" <oldw...@inspire.net.nzwrote:

好​​吧,我们最近有两个关于工会的漫长而偶然的线索,

我仍​​然不觉得什么是允许的更接近确定

和什么不是。其他主题话题是Real Life Unions

和union {unsigned char u [10]; ...}"。


这是一个具体的例子:


#include< stdio.h>


int main(无效)

{

union {int s;我们没有签名; } u;


u.us = 50;

printf("%d \ nn",us);

返回0;

}


这个程序定义明确(打印50),实现定义,还是

UB ?


请注意,这里没有违反C99 6.5中的别名规则 - 在该部分下不禁止
访问某些类型的对象T
带有左值表达式的
,其类型是T的有符号或无符号

版本。


换句话说,有没有什么

限制免费使用工会的别名规则除外?
Ok, we''ve had two long and haphazard threads about unions recently,
and I still don''t feel any closer to certainty about what is permitted
and what isn''t. The other thread topics were "Real Life Unions"
and "union {unsigned char u[10]; ...} ".

Here''s a concrete example:

#include <stdio.h>

int main(void)
{
union { int s; unsigned int us; } u;

u.us = 50;
printf("%d\n", u.s);
return 0;
}

Is this program well-defined (printing 50), implementation-defined, or
UB ?

Note that the aliasing rules in C99 6.5 are not violated here -- it is
not forbidden under that section to access an object of some type T
with an lvalue expression whose type is the signed or unsigned
version of T.

In other words, is there anything other than the aliasing rules that
restrict ''free'' use of unions?



C89:未定义。

未定义,因为访问的联盟成员不是

成员最后存储,这在标准中明确说明。


C99:定义明确。

在C99中,别名规则和表示要求确定

这种情况​​下的合法性。正如您所指出的,您的示例并没有违反别名规则,因此您在那里很好。标准

明确指出给定有符号整数类型及其对应的无符号类型的任何

共有的非负值集合具有

两种类型都有相同的表示形式,所以你也很好。


Robert Gamble

C89: undefined.
It is undefined because the member of the union accessed is not the
member last stored, this is explicitly stated in the Standard.

C99: well-defined.
In C99 the aliasing rules and representation requirements determine
the legitimacy in this case. As you noted, your example does not
violate the aliasing rules so you are good there. The Standard
explicitly states that the set of non-negative values common to any
given signed integer type and its corresponding unsigned type have the
same representations in both types so you are good there as well.

Robert Gamble


这篇关于工会Redux的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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