指向高低字节的东西 [英] Pointing to high and low bytes of something

查看:75
本文介绍了指向高低字节的东西的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的代码包含此声明:


:typedef union {

:word word;

:struct {

:字节低;

:字节高;

:}字节;

:} reg;


冒号不是声明的一部分。


假设''word''始终是16位无符号整数类型,并且

''byte''在我的实现中总是一个8位无符号整数类型(''unsigned short int''

和''unsigned char'')。


在浏览了之前的线程和

其他新闻组之后,我的理解是给出一个类型为reg的变量Var,访问

Var.Word将值分配给Var.Bytes.Low和

Var.Bytes.High,或相反,访问Var.Bytes.Low和

Var。 Bytes.High在为Var.Word分配了一个值之后,得到了实现定义的b
行为(或可能是未定义的行为)。


如果它确实是实现定义的行为,我的问题是:可以

实现只能自由选择是否

Var.Bytes.Low或Var.Bytes.High将包含Var.Word的LSB,以及

是否为Var.Bytes.High或Var.Bytes.Low将包含MSB,或者可以实现其他自由吗?


直观地说,我会说有更多这个(具体来说,

编译器可以在

Bytes结构的第一个成员之后插入填充,但是我读过的一些文章似乎暗示了其他。


无论如何,这一切都归结为:假设我愿意牺牲

可移植性,强迫维护者交换两个字节的成员

取决于实施;然后我有一个

保证Var.Bytes.Low将始终评估为

Var.Word的LSB,并且Var.Bytes.High将始终评估为MSB

Var.Word?


如果没有,那么我很乐意接受有关如何更改我的

代码的建议。

请记住,我需要访问:

1)Var.Word(或更改后的等价物)地址

2 )Var.Bytes.Low(或其等价物)按地址

3)Var.Bytes.High(或其等价物)按地址

表示此代码可以可以直接修改

按预期工作:


:#include< stdlib.h>

:#include< stdio.h>



:int main(){

:reg Var;

:reg * VarWordP;

:reg * VarLSBP;

:reg * VarMSBP;

:VarWordP =&(Var.Word );

:VarLSBP =&(Var.Bytes.Low);

:VarM SBP =&(Var.Bytes.High);

:* VarWordP = 0x1234;

:printf("%x%x%x \ n", * VarWordP,* VarLSBP,* VarMSBP);

:返回0;

:}


假设已定义类型reg如上。我应该总是得到

1234 34 12

作为程序的输出,保存

printf中可能需要的任何更改( )格式说明符。

by LjL
lj****@tiscali.it

解决方案

dl ***** @ tiscalinet.it (Lorenzo J. Lucchini)写道:

:typedef union {
:word word;
:struct {
:byte Low;
:字节高;
:}字节;
:} reg;
假设''word''总是一个16位无符号整数类型,并且''byte''总是一个8位无符号整数类型(''unsigned short int''
和''unsigned char''分别在我的实现上)。
如果它确实是实现定义的行为,我的问题是:可以实现只需自由选择是否Var.Bytes.Low或Var.Bytes.High将包含LSB Var.Word,以及
Var.Bytes.High或Var.Bytes.Low是否会包含MSB,还是可以实现其他自由?

直观地说,我会说还有更多(具体来说,编译器可以在
Bytes结构的第一个成员之后插入填充),但我读过的一些文章似乎暗示不然。




他们可以,但我从来没有见过一个这样做;可能是这样做的实施稀缺实际上是因为他们不相信

的原因之一。


Richard


lj****@tiscalinet.it (Lorenzo J. Lucchini写道:

#我的代码包含这个声明:



#:typedef union {

#:word word;

#:struct {

#:byte low;

#:byte high;

#:}字节;

#:} reg;


#无论如何,这一切都归结为:假设我愿意牺牲

#可移植性通过强制维护者交换位置


如果你愿意牺牲可移植性,那么在每台机器上试试这个

你感兴趣,如果它在那里工作,你就完成了。你也可以在main()中进行动态测试,或许,

{

reg x; x.Word = 0x1234;

if(x.Bytes.Low == 0x34&& x.Bytes.High == 0x12)

puts(" reg好的");

else if(x.Bytes.Low == 0x12&& x.Bytes.High == 0x34)

puts(" reg byte) -swabbed");

else

put(reg完全混淆);

}


-

Derk Gwen http:/ /derkgwen.250free.com/html/index.html

下降硫磺就像耐力试验一样,男人。种族灭绝是人们可以参与的最耗费精力的活动。足球旁边。


In< 1f ******** ******************@posting.google.com> lj****@tiscalinet.it (Lorenzo J. Lucchini)写道:

我的代码包含此声明:

:typedef union {
:word word;
:struct {
:byte Low;
:byte high;
:}字节;
:} reg;

冒号不是声明的一部分。

假设''word''总是一个16位无符号整数类型,并且
''byte''总是一个8位无符号整数类型('unsigned short int''
和''unsigned char''分别在我的实现)。

我在浏览了这个和其他新闻组的前一个主题之后的理解是,给定一个类型为reg的变量Var,在分配后访问
Var.Word值为Var.Bytes.Low和
Var.Bytes.High,或相反,在为Var.Word分配值后访问Var.Bytes.Low和
Var.Bytes.High,结果为< br。> im plementation-defined行为(或可能是未定义的行为)。


访问Var.Bytes.High和Var.Bytes.Low(在初始化Var.Word之后)

将始终提供实现定义的结果,没有可能

未定义的行为。但不是相反。

如果它确实是实现定义的行为,我的问题是:可以实现只能自由选择是否Var.Bytes。低或Var.Bytes.High将包含Var.Word的LSB,并且
Var.Bytes.High或Var.Bytes.Low是否包含MSB,或者可以实现其他自由吗?

直觉上,我会说还有更多(具体来说,编译器可以在
Bytes结构的第一个成员之后插入填充),但有些文章我阅读似乎暗示不然。


你的直觉是正确的:理论上,编译器*可以*做到这一点。

实际上,填充字节仅在它们服务于*时插入*

目的。在低和高之间插入填充字节将是完全不正确的,因为,*在您的假设*的框架内,没有

填充字节是完全需要的:你只是将两个字节的对象别名

两个独立的字节。

无论如何,这一切都归结为:假设我愿意牺牲
通过强制维护者根据实现交换两个字节成员的位置来实现可移植性;然后我有一个
保证Var.Bytes.Low将始终评估为
Var.Word的LSB,并且Var.Bytes.High将始终评估为
Var的MSB 。字?


在实践中,是的,假设您的初始假设仍然存在。

如果没有,那么我很乐意接受有关如何更改我的建议的建议>代码。
请记住,我需要访问:
1)Var.Word(或更改后的等价物)地址
2)Var.Bytes.Low(或等价物) )按地址
3)Var.Bytes.High(或其等价物)按地址
表示可以直接修改此代码
按预期工作:

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

:int main(){
:reg Var;
:reg * VarWordP;
:reg * VarLSBP;
:reg * VarMSBP;
:VarWordP =&(Var.Word);
:VarLSBP =&(Var.Bytes.Low);
:VarMSBP =&(Var.Bytes.High);
:* VarWordP = 0x1234;
:printf("%x% x%x \ n",* VarWordP,* VarLSBP,* VarMSBP);
:return 0;
:}

假设类型reg已定义如上。我应该总是得到程序的输出,保存
printf()格式说明符中可能需要的任何更改。




为此,你根本不需要工会:


字foo,* wp =& foo;

byte * ph,* pl;

pl =(byte *)wp; / *或反过来,取决于* /

ph = pl + 1; / *实现* /

* wp = 0x1234;

printf("%x%x%x \ n",(unsigned)* wp,(unsigned) * lp,(unsigned)* hp);


现在,即使是最不正常的编译器也不会影响你的
代码的行为:你指的是直接在foo的两个字节处,不使用

任何结构和联合。唯一(不可避免的)假设(除了在你的帖子开头明确说明的

)是关于

中的哪一个单词的两个字节是LSB和其中MSB。


另请注意printf调用中的强制转换:%x期望无符号值和

无法保证三个值中的任何一个将被提升为

这种类型(签名int更有可能)。所以,你必须明确地提供

正确的类型(再次,代码将在没有演员表的情况下工作

在实践中,但你没有做任何事情正确的事情)。


Dan

-

Dan Pop

DESY Zeuthen,RZ集团

电子邮件: Da*****@ifh.de


My code contains this declaration:

: typedef union {
: word Word;
: struct {
: byte Low;
: byte High;
: } Bytes;
: } reg;

The colons are not part of the declaration.

Assume that ''word'' is always a 16-bit unsigned integral type, and that
''byte'' is always an 8-bit unsigned integral type (''unsigned short int''
and ''unsigned char'' respectively on my implementation).

My understanding, after browsing through previous threads on this and
other newsgroup, is that given a variable Var of type reg, accessing
Var.Word after having assigned values to Var.Bytes.Low and
Var.Bytes.High or, conversely, accessing Var.Bytes.Low and
Var.Bytes.High after having assigned a value to Var.Word, results in
implementation-defined behavior (or possibly undefined behavior).

If it is indeed implementation-defined behavior, my question is: can
the implementation only take the liberty to choose whether
Var.Bytes.Low or Var.Bytes.High will contain the LSB of Var.Word, and
whether Var.Bytes.High or Var.Bytes.Low will contains the MSB, or can
the implementation take other liberties?

Intuitively, I would say that there is more than this (specifically,
that the compiler can insert padding after the first member of the
Bytes struct), but some articles I''ve read seemed to imply otherwise.

Anyway, it all comes down to: assume that I am willing to sacrifice
portability by forcing the maintainer to exchange the positions of the
two members of Bytes depending on the implementation; do I then have a
guarantee that Var.Bytes.Low will always evaluate to the LSB of
Var.Word, and that Var.Bytes.High will always evaluate to the MSB of
Var.Word?

If not, then I would gladly accept suggestions on how to change my
code.
Keep in mind that I need to access:
1) Var.Word (or its equivalent after the change) by address
2) Var.Bytes.Low (or its equivalent) by address
3) Var.Bytes.High (or its equivalent) by address
to the effect that this code can be modified in a straight-forward way
to work as intended:

: #include <stdlib.h>
: #include <stdio.h>
:
: int main() {
: reg Var;
: reg *VarWordP;
: reg *VarLSBP;
: reg *VarMSBP;
: VarWordP=&(Var.Word);
: VarLSBP=&(Var.Bytes.Low);
: VarMSBP=&(Var.Bytes.High);
: *VarWordP=0x1234;
: printf("%x %x %x\n", *VarWordP, *VarLSBP, *VarMSBP);
: return 0;
: }

Assume type reg has been defined as above. I should always get
1234 34 12
as the program''s output, save any changes that could be needed in the
printf() format specifiers.
by LjL
lj****@tiscali.it

解决方案

dl*****@tiscalinet.it (Lorenzo J. Lucchini) wrote:

: typedef union {
: word Word;
: struct {
: byte Low;
: byte High;
: } Bytes;
: } reg; Assume that ''word'' is always a 16-bit unsigned integral type, and that
''byte'' is always an 8-bit unsigned integral type (''unsigned short int''
and ''unsigned char'' respectively on my implementation). If it is indeed implementation-defined behavior, my question is: can
the implementation only take the liberty to choose whether
Var.Bytes.Low or Var.Bytes.High will contain the LSB of Var.Word, and
whether Var.Bytes.High or Var.Bytes.Low will contains the MSB, or can
the implementation take other liberties?

Intuitively, I would say that there is more than this (specifically,
that the compiler can insert padding after the first member of the
Bytes struct), but some articles I''ve read seemed to imply otherwise.



They can, but I''ve never seen one that does; probably the scarcity of
implementations that do so is part of the reason for the belief that
they can''t.

Richard


lj****@tiscalinet.it (Lorenzo J. Lucchini) wrote:
# My code contains this declaration:
#
# : typedef union {
# : word Word;
# : struct {
# : byte Low;
# : byte High;
# : } Bytes;
# : } reg;

# Anyway, it all comes down to: assume that I am willing to sacrifice
# portability by forcing the maintainer to exchange the positions of the

If you''re willing to sacrafice portability, then try this on each machine
you''re interested in, and if it works there, you''re done. You can also
have a dynamic test in main(), perhaps,
{
reg x; x.Word = 0x1234;
if (x.Bytes.Low==0x34 && x.Bytes.High==0x12)
puts("reg okay");
else if (x.Bytes.Low==0x12 && x.Bytes.High==0x34)
puts("reg byte-swabbed");
else
puts("reg completely confused");
}

--
Derk Gwen http://derkgwen.250free.com/html/index.html
Raining down sulphur is like an endurance trial, man. Genocide is the
most exhausting activity one can engage in. Next to soccer.


In <1f**************************@posting.google.com > lj****@tiscalinet.it (Lorenzo J. Lucchini) writes:

My code contains this declaration:

: typedef union {
: word Word;
: struct {
: byte Low;
: byte High;
: } Bytes;
: } reg;

The colons are not part of the declaration.

Assume that ''word'' is always a 16-bit unsigned integral type, and that
''byte'' is always an 8-bit unsigned integral type (''unsigned short int''
and ''unsigned char'' respectively on my implementation).

My understanding, after browsing through previous threads on this and
other newsgroup, is that given a variable Var of type reg, accessing
Var.Word after having assigned values to Var.Bytes.Low and
Var.Bytes.High or, conversely, accessing Var.Bytes.Low and
Var.Bytes.High after having assigned a value to Var.Word, results in
implementation-defined behavior (or possibly undefined behavior).
Accessing Var.Bytes.High and Var.Bytes.Low (after initialising Var.Word)
will always provide implementation-defined results, with no possibility
of undefined behaviour. But not the other way round.
If it is indeed implementation-defined behavior, my question is: can
the implementation only take the liberty to choose whether
Var.Bytes.Low or Var.Bytes.High will contain the LSB of Var.Word, and
whether Var.Bytes.High or Var.Bytes.Low will contains the MSB, or can
the implementation take other liberties?

Intuitively, I would say that there is more than this (specifically,
that the compiler can insert padding after the first member of the
Bytes struct), but some articles I''ve read seemed to imply otherwise.
Your intuition is correct: in theory, the compiler *can* do that.
In practice, padding bytes are inserted only when they serve a *good*
purpose. Inserting padding byte(s) between Low and High would be
downright perverse, since, *in the framework of your assumptions*, no
padding bytes are needed at all: you''re merely aliasing a two-byte object
by two independent bytes.
Anyway, it all comes down to: assume that I am willing to sacrifice
portability by forcing the maintainer to exchange the positions of the
two members of Bytes depending on the implementation; do I then have a
guarantee that Var.Bytes.Low will always evaluate to the LSB of
Var.Word, and that Var.Bytes.High will always evaluate to the MSB of
Var.Word?
In practice, yes, assuming that your initial assumptions still hold.
If not, then I would gladly accept suggestions on how to change my
code.
Keep in mind that I need to access:
1) Var.Word (or its equivalent after the change) by address
2) Var.Bytes.Low (or its equivalent) by address
3) Var.Bytes.High (or its equivalent) by address
to the effect that this code can be modified in a straight-forward way
to work as intended:

: #include <stdlib.h>
: #include <stdio.h>
:
: int main() {
: reg Var;
: reg *VarWordP;
: reg *VarLSBP;
: reg *VarMSBP;
: VarWordP=&(Var.Word);
: VarLSBP=&(Var.Bytes.Low);
: VarMSBP=&(Var.Bytes.High);
: *VarWordP=0x1234;
: printf("%x %x %x\n", *VarWordP, *VarLSBP, *VarMSBP);
: return 0;
: }

Assume type reg has been defined as above. I should always get
1234 34 12
as the program''s output, save any changes that could be needed in the
printf() format specifiers.



You don''t need the union at all for this purpose:

word foo, *wp = &foo;
byte *ph, *pl;
pl = (byte *)wp; /* or the other way round, depending on the */
ph = pl + 1; /* implementation */
*wp = 0x1234;
printf("%x %x %x\n", (unsigned)*wp, (unsigned)*lp, (unsigned)*hp);

Now, even the most perverse compiler cannot affect the behaviour of your
code: you''re pointing at the two bytes of foo directly, without using
any structs and unions. The only (unavoidable) assumption (apart from the
ones explicitly stated at the beginning of your post) is about which of
the two bytes of a word is the LSB and which the MSB.

Also note the casts in the printf call: %x expects an unsigned value and
there is no guarantee that any of the three values will get promoted to
this type (signed int is far more probable). So, you must provide the
right type explicitly (again, the code will work without the casts as well
in practice, but you have nothing to gain by not doing the right thing).

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de


这篇关于指向高低字节的东西的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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