C标准问题? [英] C standard question?

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

问题描述

赋值语句右侧的变量

是否严格视为值?也就是说,如果分配给unsigned

int,我移动了一个unsigned char。左边24个地方,我可以相信,编译器将使用足够的临时存储来保存无符号的

int。并且不会导致溢出(因为我移动了unsigned

char24个地方)?


使用gcc我尝试了以下代码:


#include< stdio.h>


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

{

unsigned char c [4] = {0xff,0xff,0xff,0xff};

unsigned int ui;


ui =(c [3] << 24)| (c [2]<< 16)| (c [1]<< 8)| c [0];

fprintf(stderr," ui =%x \ n",ui);

}


并得到:

Are the variables on the righthand side of an assignment statement
treated strictly as values? That is, if in assigning to an "unsigned
int" I shift a "unsigned char" 24 places to the left, can I trust that
the compiler will use temp storage sufficient to hold the "unsigned
int" and NOT result in an overflow (because I shifted an "unsigned
char" 24 places)?

Using gcc I tried the code below:

#include <stdio.h>

int main( int argc, char *argv[] )
{
unsigned char c[ 4 ] = { 0xff, 0xff, 0xff, 0xff };
unsigned int ui;

ui = (c[ 3 ] << 24) | (c[ 2 ] << 16) | (c[ 1 ] << 8) | c[ 0 ];
fprintf( stderr, "ui = %x\n", ui );
}

and got:


ui = ffffffff
ui = ffffffff



但是通过编译进行验证是一件危险的事情!


--- jski

But validation through compilation is a dangerous thing!

---jski

推荐答案

ja ************* @ gmail.com 写道:

赋值语句右侧的变量

是否严格视为值?
Are the variables on the righthand side of an assignment statement
treated strictly as values?



不,但主要是肯定的。在& x或

`sizeof x'的右侧,变量x仅用于其位置

或其类型,而不是它的价值。但在算术

右侧,如x + 3或x<< 2''或只是'x'',使用

变量'的值。

No, but mostly yes. In right-hand sides like `&x'' or
`sizeof x'', the variable `x'' is used only for its location
or for its type, not for its value. But in "arithmetic"
right-hand sides like `x + 3'' or `x << 2'' or just `x'', the
variable''s value is used.


也就是说,如果在分配给unsigned

int我移动了一个unsigned char。左边24个地方,我可以相信,编译器将使用足够的临时存储来保存无符号的

int。并且不会导致溢出(因为我移动了未签名的

char24个地方)?
That is, if in assigning to an "unsigned
int" I shift a "unsigned char" 24 places to the left, can I trust that
the compiler will use temp storage sufficient to hold the "unsigned
int" and NOT result in an overflow (because I shifted an "unsigned
char" 24 places)?



编号分配目标 - 左侧 - 确实

不影响右侧的评估方式。在大多数

系统[*]上,你的`unsigned char''值将被提升为

plain(signed)`int'',然后将向左移动24地方。

如果'int''有24个或更少的位(16,对于

例子),或者如果班次试图滑动非-zero位从

a值位置到标志位置。


你需要的是


unsigned char uc = ...;

unsigned int ui =(unsigned int)uc<< 24;


....这仍然包含'int''在

至少25位宽的假设。

[*]例外:在异国情调上系统就像一些数字信号

处理器,字符和整数具有相同的宽度,并且

`unsigned char''会提升为`unsigned int''。

No. The assignment target -- the left-hand side -- does
not influence how the right-hand side is evaluated. On most
systems[*] your `unsigned char'' value will be promoted to a
plain (signed) `int'', which will then be shifted left 24 places.
There''ll be trouble if `int'' has 24 or fewer bits (16, for
example), or if the shift tries to slide a non-zero bit from
a value position into the sign position.

What you need is

unsigned char uc = ...;
unsigned int ui = (unsigned int)uc << 24;

.... and this still contains the assumption that `int'' is at
least 25 bits wide.
[*] Exception: On "exotic" systems like some digital signal
processors, characters and ints have the same width and an
`unsigned char'' promotes to an `unsigned int'' instead.


使用gcc我尝试了下面的代码:


#include< stdio.h>


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

{

unsigned char c [4] = {0xff,0xff,0xff,0xff};

unsigned int ui;


ui =(c [3]<< 24)| (c [2]<< 16)| (c [1]<< 8)| c [0];

fprintf(stderr," ui =%x \ n",ui);

}


并得到:
Using gcc I tried the code below:

#include <stdio.h>

int main( int argc, char *argv[] )
{
unsigned char c[ 4 ] = { 0xff, 0xff, 0xff, 0xff };
unsigned int ui;

ui = (c[ 3 ] << 24) | (c[ 2 ] << 16) | (c[ 1 ] << 8) | c[ 0 ];
fprintf( stderr, "ui = %x\n", ui );
}

and got:

> ui = ffffffff
>ui = ffffffff



你很幸运。或者也许是运气不好。

You were lucky. Or maybe unlucky.


但是通过编译进行验证是一件危险的事情!
But validation through compilation is a dangerous thing!



我说过不可靠而不是危险的,而不是危险的。但

情绪是对的。


-
Er ********* @ sun.com


5月7日,8:20 * pm,Eri​​c Sosman < Eric.Sos ... @ sun.comwrote:
On May 7, 8:20*pm, Eric Sosman <Eric.Sos...@sun.comwrote:

* * * * unsigned int ui =(unsigned int)uc<< 24;
* * * * unsigned int ui = (unsigned int)uc << 24;



你不会相信有多少人喜欢以下这类:


char unsigned uc1,uc2;


uc1 = 72;


uc2 = ~uc1;


1)uc1升级到一个签名的int

2)补充得到这个签名的int

3)当signed int被转换回unsigned char时,

行为是实现定义的。


两个补码系统没有问题,当然大多数b / b
系统都是两个'补充,但我肯定会选择:


uc2 =〜(无符号)uc1;


You wouldn''t believe how many people do the likes of the following:

char unsigned uc1, uc2;

uc1 = 72;

uc2 = ~uc1;

1) uc1 gets promoted to a signed int
2) The complement is gotten of this signed int
3) When the signed int is converted back to unsigned char, the
behaviour is implementation defined.

There''s no problem on a two''s complement system, and of course most
systems are two''s complement, but still I''d definitely go with:

uc2 = ~(unsigned)uc1;


< a href =mailto:ja ************* @ gmail.com> ja ************* @ gmail.com 写道,在08/05/08 19:44:
ja*************@gmail.com wrote, On 07/05/08 19:44:

赋值语句右侧的变量

是否严格视为值?
Are the variables on the righthand side of an assignment statement
treated strictly as values?



这不是你打算问的问题。我想你想知道

如果他们被视为与左手边相同类型的值,

,答案是否定的。

That is not the question you intended to ask. I think you wanted to know
if they are treated as values of the same type as the left hand side,
and the answer is no.


也就是说,如果分配给unsigned

int我移动了一个unsigned char。左边24个地方,我可以相信,编译器将使用足够的临时存储来保存无符号的

int。并且不会导致溢出(因为我移动了unsigned

char24个地方)?


使用gcc我尝试了以下代码:


#include< stdio.h>


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

{

unsigned char c [4] = {0xff,0xff,0xff,0xff};

unsigned int ui;


ui =(c [3] << 24)| (c [2]<< 16)| (c [1]<< 8)| c [0];
That is, if in assigning to an "unsigned
int" I shift a "unsigned char" 24 places to the left, can I trust that
the compiler will use temp storage sufficient to hold the "unsigned
int" and NOT result in an overflow (because I shifted an "unsigned
char" 24 places)?

Using gcc I tried the code below:

#include <stdio.h>

int main( int argc, char *argv[] )
{
unsigned char c[ 4 ] = { 0xff, 0xff, 0xff, 0xff };
unsigned int ui;

ui = (c[ 3 ] << 24) | (c[ 2 ] << 16) | (c[ 1 ] << 8) | c[ 0 ];



每个数组元素将被提升为int(如果UCHAR_MAX< =

INT_MAX)或unsigned int(如果INT_MAX< UCHAR_MAX) < = UINT_MAX)。由于

后者可能是你的gcc实现的情况c [3]<< 24引用了

未定义的行为。

Each array element will be promoted to either int (if UCHAR_MAX <=
INT_MAX) or unsigned int (if INT_MAX < UCHAR_MAX <= UINT_MAX). Since the
latter is probably the case on your gcc implementation c[3]<<24 invoked
undefined behaviour.


fprintf(stderr," ui =%x \ n",ui);

}


并得到:
fprintf( stderr, "ui = %x\n", ui );
}

and got:

> ui = ffffffff
>ui = ffffffff



但是通过编译进行验证是一件危险的事情!


But validation through compilation is a dangerous thing!



事实上,由于在这种情况下行为未定义,因此它是运气。你得到了你想要的答案。
你应该转换为正确的无符号类型。

还要注意(unsigned)int只能是16位。

-

Flash戈登

Indeed, as the behaviour is undefined in this case it was "luck" you got
the answer you expected. You should cast to the correct unsigned type.
Also be aware that (unsigned) int could be only 16 bits.
--
Flash Gordon


这篇关于C标准问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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