char和int的问题?
时间:2008-05-14 10:37:19
来源:论坛整理 作者: 编辑:chinaitzhe
6:设a为char类型,b为int类型,那么a = (char)b等效于 a = *(char *)&b; ×
希望高手帮忙分析一下。
网友回复:6涉及到大小端存储的问题了!
网友回复:麻烦具体解释一下,这两天就看big-endian和little-endian了。
呵呵
网友回复:了解一些内存数据存储结构,涉及到高低字节的问题
网友回复:int型占4字节,char型占1字节,数据结构如下,一个字节占8位二进制
b:
¦8bits ¦ ¦8bits ¦ ¦8bits ¦ ¦8bits ¦
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
a:
¦8bits ¦
xxxxxxxx
0xff是十六进制,换算成10进制就是255 = 2^8 - 1,二进制的表现形式是:
¦8bits ¦ ¦8bits ¦ ¦8bits ¦ ¦8bits ¦
00000000 00000000 00000000 11111111
b & 0xff进行了按位与的运算,就是2进制上相同位置的数字都是1的时候,结果才是1
因此 b & oxff 实际上对b进行了截断,因为0xff除了第24为为1意外,其他都是0,因此
b & 0xff的结果是
00000000 00000000 00000000 xxxxxxxx
而这最后的8位是和b的最后8位一样的,因为0 & 1 = 0, 0 & 0 = 1, 1 & 1 = 1;
(char)b的意思就是对b进行强制转换,对b的数据进行截断,取的也是b对最后8位
因此 a = (char)b等效于 a = b & 0xff;
网友回复:前面那个有点问题,重发一遍
int型占4字节,char型占1字节,数据结构如下,一个字节占8位二进制
b:
|8bits | |8bits | |8bits | |8bits |
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
a:
|8bits |
xxxxxxxx
0xff是十六进制,换算成10进制就是255 = 2^8 - 1,二进制的表现形式是:
|8bits | |8bits | |8bits | |8bits |
00000000 00000000 00000000 11111111
b & 0xff进行了按位与的运算,就是2进制上相同位置的数字都是1的时候,结果才是1
因此 b & oxff 实际上对b进行了截断,因为0xff除了最后8为是1以外,其他都是0,
因此,b & 0xff的结果是
00000000 00000000 00000000 xxxxxxxx
而这最后的8位是和b的最后8位一样的,因为0 & 1 = 0, 0 & 0 = 1, 1 & 1 = 1;
(char)b的意思就是对b进行强制转换,对b的数据进行截断,取的也是b对最后8位
因此 a = (char)b等效于 a = b & 0xff;
网友回复:非常感谢matrixdwy的回答,你的回答很详尽,写这么多确实很不轻易,真的要感谢一下。
为什么a = *(char *)&b;就不对呢?这一段按照matrixdwy的方式分析该如何分析呢?
谢谢!
网友回复:后面一个同样不懂,等待高手
网友回复: a = b & 0xff 保留0~7位等效于a = (char)b
a = *(char *)&b
取b的地址32位,强转为指向char类型的指针,还是32位.并为赋初值,再*还是b本身吧也就是int b
=================================================================================
个人的想法不代表正解
网友回复:mark
网友回复:用union来测试是大端还是小端...
- C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ #include <stdio.h> union Test { int i; char c; }; int main() { Test ts; ts.i = 1; printf("%d", (int)ts.c); return 0; }
网友回复:
对于这个我是这样理解的 不知道对不对\
(char *)&b //是指把整形变量b 的地址强制转换为char 型的指针
a=*(char*)&b;// 赋值后 即&a==&b;
假设 b=0x00000041;存放在地址为0x10000000 的内存空间中
假如计算机是big-endian型的
则内存空间的内容是:
0x10000000 00
0x10000001 00
0x10000002 00
0x10000003 41
所以 &a=0x10000000 a=00;所以是错误的
假如计算机是little-endian型的
则内存空间的内容是:
0x10000000 41
0x10000001 00
0x10000002 00
0x10000003 00
所以 &a=0x10000000 a=41=b;这样就是正确的
网友回复:上面分析的不对
网友回复:晕我指8楼
网友回复:现在想想反倒更迷惑了。
假设:
int b = 0x1234abcd
那么它在内存中实际的存储是cd ab 34 12
假如 a = b & 0xff应该是等价于a = b & 0x000000ff,这样的话应该是a = 12才对啊。
char指针和int指针又存在着哪些本质上的区别与联系呢?
望高手指点一下
网友回复:假如低位在前,高位在后,一般的数据存储,a = (char)b等效于 a = *(char *)&b;这就没错
因为一个int 4个字节,&b就是取int b的最低位byte的地址,然后将这个地址转换成char*类型,再取它的内容,这就没错
假如高位在前,低位在后,比如网络上数据发送,那就有问题了,&b是取int的最高位byte。这样的话a = (char)b应该等效于 a = *(((char *)&b) 3);
网友回复:
为什么不肯自己调试一下看看呢?
- C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ #include <stdio.h> int main() { int i; int num = 0x12345678; char* ptr = (char*) # for (i = 0 ; i < 4; i ) { printf("%p\t%x\n", ptr, *ptr); ptr ; } return 0; }
网友回复:看看内存布局,和内存地址内对应的存储的数字...
网友回复:
内存存储是内存存储,和计算是2样的
a = b & 0xff应该是等价于a = b & 0x000000ff,那么你把b的值替换掉,b = 0x1234abcd
那么就是a = 0x1234abcd & 0x000000ff; a=0xcd;
网友回复:嗯,明白了。
感谢lixun_21、greatws和fetag
lixun_21让我初步理解了这个原因,
但a=*(char*)&b;// 赋值后 即&a==&b; 这个注释我觉得似乎有点问题,他俩的地址应该是不一样的。
greatws让我真正地理解了本质。
fetag让我知道了输出指针可以用%p来输出。
结帖
网友回复:对了,我还想对第一个问题再分析一下,如有错误还希望指正一下。
设a为char类型,b为int类型,那么a = (char)b等效于 a = b & 0xff;
假设b = 0x12345678,a = (char)b等价于取b地址的第一个字节,0xff应该当作一个整型来看待,即0x000000ff.
假设存储是little-endian,那么在内存中b的实际存储为78 56 34 12,0xff为ff 00 00 00,那么b & 0xff在内存中是78 00 00 00,元算后又得转换显示出00 00 00 78即78.
假设存储是big-endian,那么在内存中b的实际存储为12 34 56 78,0xff为00 00 00 78,那么 b & 0xff在内存中
是00 00 00 00 78,运算后不需转换显示出00 00 00 78.
由此我想到一点,就是little-endian的存储需要两次转换,而big-endian的存储不需要转换。
网友回复:研究研究
网友回复:
两个都不对嘛!
第一个对小于-128的数是不对的(至少在部分编译器上是不对的)。
第二个对于MSB的机器是不对的。
- C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ #include <stdio.h> int main(void) { char c; int i; i = -300; c = i; printf("%d\n", (int)c); c = i && 0xff; printf("%d\n", (int)c); c = *(char *)&i; printf("%d\n", (int)c); return 0; }
在FreeBSD 6.2-RELEASE amd64用gcc (GCC) 3.4.6 [FreeBSD] 20060305编译后
输出为:
-44
1
-44
在SunOS 5.10 sun4v用gcc version 4.0.3 (gccfss)输出为
输出为:
-44
1
-1
网友回复:学习
网友回复:输出的结果的值是一样的啊。
可能理论上含义不同吧,但是输出结果是一样的。
我是在intel,windows下测试的。
不知道在mac机上是否也是一样。
网友回复:int main()
{
int b = 0x12345678;
char a = 0;
char c = 0;
a = (char)b;
printf("a = %d\n",a);
c = *(char*)&b;
printf("c = %d\n",c);
}
同样的代码,在intel机上的运行结果是:
a=120
b=120
但是在mac机上的运行结果是:
a=120
b=18
看来这真的是因为BigEndian和LittleEndian的问题。
intel机和mac机存放内存地址的字节顺序是不一样的。
网友回复:
同意。
俺也学到东西了。
网友回复:代码资料挺全,推荐一下:http://www.ciitc.com
网友回复:mark
网友回复:学习啊
网友回复:呵呵,没想到这么多人感爱好阿。
顺便再问个问题:有没有办法在Intel的CPU上模拟出big-endian的效果呢?不是通过算法之类的转化,而是不知编译器或其它可不可以改变这个属性。
网友回复:
- C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ int b = 0x30313233; // 0x30 is ascii for '0', and so on char a = (char)b; // cast from int to char: get the "last" byte 0x33 // i.e. b & 0xff char a = *(char*)&b; // get the byte pointed by the "&b" // cast to make "&b" a char pointer bin-endian: base_address 3: |0x33| base_address 2: |0x32| base_address 1: |0x31| base_address 0: |0x30| <-- &b point here little-endian: base_address 3: |0x30| base_address 2: |0x31| base_address 1: |0x32| base_address 0: |0x33| <-- &b point here default, &b is a pointer of int and 4 bytes will be interpreted; by casting &b into a pointer of char, only 1 byte is interpreted.
- C/C code
Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ #include <stdio.h> typedef unsigned char BYTE; void print_object(const BYTE *base, int size) { printf("object is at %p\n", base); printf(" address content ascii\n"); while(size > 0) { --size; printf("base_address %d: %p | 0xX | %c\n", size, base size, *(base size), *(base size)); } } int main(void) { int b = 0x30313233; char a; print_object(&b, sizeof(b)); a = (char) b; printf("%c\n", a); a = *((char*)(&b)); printf("%c\n", a); return 0; } object is at 0xbfffe934 address content ascii base_address 3: 0xbfffe937 | 0x30 | 0 base_address 2: 0xbfffe936 | 0x31 | 1 base_address 1: 0xbfffe935 | 0x32 | 2 base_address 0: 0xbfffe934 | 0x33 | 3 3 3
网友回复:在PC机上我认为两个都对,因为int的存储是低位在前高位在后。
网友回复:呵呵 昨天刚看到有关高地端的问题 今天又遇上了
网友回复:31楼很具体
关键字:char,int,问题,
上一篇:断言宏?
下一篇:下面没有链接了











文章评论
共有 0 位网友发表了评论 此处只显示部分留言 点击查看完整评论页面