首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • char和int的问题? [已结贴,结贴人:clxye]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 17:07:25 楼主
    5:设a为char类型,b为int类型,那么a = (char)b等效于 a = b & 0xff;      √
    6:设a为char类型,b为int类型,那么a = (char)b等效于 a = *(char *)&b;    ×

    希望高手帮忙分析一下。
    10  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 17:10:011楼 得分:0
    6涉及到大小端存储的问题了!

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 17:18:252楼 得分:0
    麻烦详细解释一下,这两天就看big-endian和little-endian了。
    呵呵
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 17:21:183楼 得分:0
    了解一些内存数据存储结构,涉及到高低字节的问题
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 17:32:074楼 得分:0
    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;
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 17:36:085楼 得分:5
    前面那个有点问题,重发一遍

    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;
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 18:42:236楼 得分:0
    非常感谢matrixdwy的回答,你的回答很详尽,写这么多确实很不容易,真的要感谢一下。

    为什么a = *(char *)&b;就不对呢?这一段按照matrixdwy的方式分析该如何分析呢?
    谢谢!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 18:45:137楼 得分:0
    后面一个同样不懂,等待高手
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 19:03:198楼 得分:0
    a = b & 0xff 保留0~7位等效于a = (char)b
    a = *(char *)&b
    取b的地址32位,强转为指向char类型的指针,还是32位.并为赋初值,再*还是b本身吧也就是int b
    =================================================================================
    个人的想法不代表正解
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 19:08:159楼 得分:0
    mark
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fetag
    • 等级:
    发表于:2008-05-08 19:09:1410楼 得分:0
    用union来测试是大端还是小端...
    C/C++ code
    #include <stdio.h> union Test { int i; char c; }; int main() { Test ts; ts.i = 1; printf("%d", (int)ts.c); return 0; }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 19:09:4511楼 得分:0
    引用楼主 clxye 的帖子:
    6:设a为char类型,b为int类型,那么a = (char)b等效于 a = *(char *)&b;    ×

    对于这个我是这样理解的 不知道对不对\
    (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;这样就是正确的

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 19:11:4412楼 得分:0
    上面分析的不对
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 19:12:1513楼 得分:0
    晕我指8楼
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 19:13:1614楼 得分:0
    现在想想反倒更迷惑了。
    假设:
    int b = 0x1234abcd
    那么它在内存中实际的存储是cd ab 34 12
    如果 a = b & 0xff应该是等价于a = b & 0x000000ff,这样的话应该是a = 12才对啊。

    char指针和int指针又存在着哪些本质上的区别与联系呢?
    望高手指点一下
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 19:20:2715楼 得分:0
    如果低位在前,高位在后,一般的数据存储,a = (char)b等效于 a = *(char *)&b;这就没错
    因为一个int 4个字节,&b就是取int b的最低位byte的地址,然后将这个地址转换成char*类型,再取它的内容,这就没错


    如果高位在前,低位在后,比如网络上数据发送,那就有问题了,&b是取int的最高位byte。这样的话a = (char)b应该等效于 a = *(((char *)&b)+3);
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fetag
    • 等级:
    发表于:2008-05-08 19:22:1716楼 得分:0
    引用 14 楼 clxye 的回复:
    现在想想反倒更迷惑了。
    假设:
    int b = 0x1234abcd
    那么它在内存中实际的存储是cd ab 34 12
    如果 a = b & 0xff应该是等价于a = b & 0x000000ff,这样的话应该是a = 12才对啊。

    char指针和int指针又存在着哪些本质上的区别与联系呢?
    望高手指点一下

    为什么不肯自己调试一下看看呢?
    C/C++ code
    #include <stdio.h> int main() { int i; int num = 0x12345678; char* ptr = (char*) &num; for (i = 0 ; i < 4; i++) { printf("%p\t%x\n", ptr, *ptr); ptr++; } return 0; }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fetag
    • 等级:
    发表于:2008-05-08 19:23:0317楼 得分:0
    看看内存布局,和内存地址内对应的存储的数字...
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 19:24:3018楼 得分:0
    引用 14 楼 clxye 的回复:
    现在想想反倒更迷惑了。
    假设:
    int b = 0x1234abcd
    那么它在内存中实际的存储是cd ab 34 12
    如果 a = b & 0xff应该是等价于a = b & 0x000000ff,这样的话应该是a = 12才对啊。

    char指针和int指针又存在着哪些本质上的区别与联系呢?
    望高手指点一下



    内存存储是内存存储,和计算是2样的
    a = b & 0xff应该是等价于a = b & 0x000000ff,那么你把b的值替换掉,b = 0x1234abcd
    那么就是a = 0x1234abcd & 0x000000ff;  a=0xcd;
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 19:40:3519楼 得分:0
    嗯,明白了。
    感谢lixun_21、greatws和fetag

    lixun_21让我初步理解了这个原因,
    但a=*(char*)&b;// 赋值后 即&a==&b; 这个注释我觉得好像有点问题,他俩的地址应该是不一样的。

    greatws让我真正地理解了本质。

    fetag让我知道了输出指针可以用%p来输出。

    结帖
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 19:55:1420楼 得分:0
    对了,我还想对第一个问题再分析一下,如有错误还希望指正一下。
    设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的存储不需要转换。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 22:24:5221楼 得分:0
    研究研究
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-08 23:20:4422楼 得分:0
    引用楼主 clxye 的帖子:
    5:设a为char类型,b为int类型,那么a = (char)b等效于 a = b & 0xff;      √
    6:设a为char类型,b为int类型,那么a = (char)b等效于 a = *(char *)&b;    ×

    希望高手帮忙分析一下。

    两个都不对嘛!
    第一个对小于-128的数是不对的(至少在部分编译器上是不对的)。
    第二个对于MSB的机器是不对的。
    C/C++ code
    #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
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-09 08:02:4423楼 得分:0
    学习
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-09 09:02:4724楼 得分:0
    输出的结果的值是一样的啊。
    可能理论上含义不同吧,但是输出结果是一样的。
    我是在intel,windows下测试的。
    不知道在mac机上是否也是一样。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-09 09:09:1225楼 得分:0
    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机存放内存地址的字节顺序是不一样的。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-09 09:38:1426楼 得分:0
    引用 20 楼 clxye 的回复:
    对了,我还想对第一个问题再分析一下,如有错误还希望指正一下。
    设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.

    假设存…

    同意。
    俺也学到东西了。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-09 10:29:2527楼 得分:0
    代码资料挺全,推荐一下:http://www.ciitc.com
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-09 10:37:2728楼 得分:0
    mark
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-09 11:24:0129楼 得分:0
    学习啊
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-09 12:16:1430楼 得分:0
    呵呵,没想到这么多人感兴趣阿。
    顺便再问个问题:有没有办法在Intel的CPU上模拟出big-endian的效果呢?不是通过算法之类的转化,而是不知编译器或其它可不可以改变这个属性。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-05-09 13:57:5831楼 得分:5
    C/C++ code
    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
    #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 | 0x%02X | %c\n", size, base + size, *