| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 837 人关注过本帖
标题:请问指针类型转换和强制类型转换的区别在哪里呢
只看楼主 加入收藏
后卿
Rank: 4
来 自:网络
等 级:业余侠客
威 望:1
帖 子:302
专家分:295
注 册:2016-10-22
结帖率:81.71%
收藏
已结贴  问题点数:1 回复次数:7 
请问指针类型转换和强制类型转换的区别在哪里呢
请问指针类型转换和强制类型转换的区别在哪里呢
为什么代码1的结果和代码2的结果不一样呢?原理是什么

代码1
long ua    { 1000 };
long long* uptr    { (long long*)&ua };
std::cout << *uptr;


代码2
 
long ua    { 1000 };
long long uptr    { (long long) ua };
std::cout << uptr;


```
搜索更多相关主题的帖子: long 指针 强制 代码 类型转换 
2023-03-29 17:52
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9025
专家分:54030
注 册:2011-1-18
收藏
得分:1 
四字节的整型值 1091567616 在内存中的排布是 00 00 10 41(假设用的是little-endian)
四字节的浮点值 0.9 在内存中的排布也是 00 00 10 41
也就是说,对于内存中的四个字节 00 00 10 41,你把它当成 int32_t 看待的话,它就是 1091567616;你把它当成 float 看待的话,它就是 0.9。

你的第二段代码在编译器眼中是 4字节的整型1000 转换成 8字节的整型1000;
你的第一段代码在编译器眼中是内存中排布的 E8 03 00 00 ?? ?? ?? ?? 这8个字节当成 long long 看待是 多少
2023-03-29 21:21
后卿
Rank: 4
来 自:网络
等 级:业余侠客
威 望:1
帖 子:302
专家分:295
注 册:2016-10-22
收藏
得分:0 
回复 2楼 rjsp

第二段代码四字节的1000转换成8字节的1000,内存地址变了吗?请问它是哪里变了呢?
第一段代码,转换了指针类型后,地址变了吗?第一段代码的ua,假设地址是0x0001,转换成long long 型,变成了0x0001xxxx,xxxx不知道是多少,所以输出结果也不确定,是这个意思吗
2023-03-30 08:58
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9025
专家分:54030
注 册:2011-1-18
收藏
得分:0 
第二段代码四字节的1000转换成8字节的1000,内存地址变了吗?请问它是哪里变了呢?
没有地址,在编译器眼中,就是 long值1000 转化成 long long值1000.

第一段代码,转换了指针类型后,地址变了吗?第一段代码的ua,假设地址是0x0001,转换成long long 型,变成了0x0001xxxx,xxxx不知道是多少,所以输出结果也不确定,是这个意思吗
地址没变;
不仅仅是所指字节数量不一致,而是这违规了「严格别名」规则,成为未定义行为
2023-03-30 12:14
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9025
专家分:54030
注 册:2011-1-18
收藏
得分:0 
程序代码:
#include <cstdio>
#include <cstdint>
#include <cinttypes>
#include <bit>

int main( void )
{
    float a = 123.25f;
    printf( "float   %12g 占据 %zu 字节,它在内存中的数据是 0x%02hhX 0x%02hhX 0x%02hhX 0x%02hhX\n"
        , a
        , sizeof(a)
        , ((unsigned char*)(&a))[0]
        , ((unsigned char*)(&a))[1]
        , ((unsigned char*)(&a))[2]
        , ((unsigned char*)(&a))[3] );

    int32_t b = 1123450880;
    printf( "int32_t %12" PRId32 " 占据 %zu 字节,它在内存中的数据是 0x%02hhX 0x%02hhX 0x%02hhX 0x%02hhX\n"
        , b
        , sizeof(b)
        , ((unsigned char*)(&b))[0]
        , ((unsigned char*)(&b))[1]
        , ((unsigned char*)(&b))[2]
        , ((unsigned char*)(&b))[3] );

    int32_t c = (int32_t)a;
    printf( "将 float %g 转化成 int32_t 类型后,值为 %" PRId32 "\n", a, c );

    int32_t d = *(int32_t*)&a;
    printf( "将 float %g 所占内存当成 int32_t 类型格式,则值为 %" PRId32 " ------ 需要注意的是,这是未定义行为\n", a, d );

    int32_t e = std::bit_cast<int32_t>( a );
    printf( "将 float %g 所占内存当成 int32_t 类型格式,则值为 %" PRId32 " ------ 使用memcpy或std::bit_cast才是良好定义行为\n", a, e );
}


输出
float         123.25 占据 4 字节,它在内存中的数据是 0x00 0x80 0xF6 0x42
int32_t   1123450880 占据 4 字节,它在内存中的数据是 0x00 0x80 0xF6 0x42

将 float 123.25 转化成 int32_t 类型后,值为 123
将 float 123.25 所占内存当成 int32_t 类型格式,则值为 1123450880 ------ 需要注意的是,这是未定义行为
将 float 123.25 所占内存当成 int32_t 类型格式,则值为 1123450880 ------ 使用memcpy或std::bit_cast才是良好定义行为
2023-03-30 12:35
后卿
Rank: 4
来 自:网络
等 级:业余侠客
威 望:1
帖 子:302
专家分:295
注 册:2016-10-22
收藏
得分:0 
回复 4楼 rjsp
好的,
float     123.25 占据 4 字节,它在内存中的数据是 0x00 0x80 0xF6 0x42
int32_t   1123450880 占据 4 字节,它在内存中的数据是 0x00 0x80 0xF6 0x42
但是这两个为什么内存地址一样,但是值却不一样呢
2023-03-30 13:18
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9025
专家分:54030
注 册:2011-1-18
收藏
得分:0 
回复 6楼 后卿
float a = 123.25f;
int32_t b = 1123450880;
这两者的地址不一样(也就是 &a != &b),但在内存中的存储数据是一样的(都是 0x00 0x80 0xF6 0x42)

打个比方,看到 a 这个字母,中国人会把它当成拼音念“阿”,英国人会把它当成英文字母念“艾”。
再打个比方,内存中两个字节 0xBA 0xC3,如果它是 GBK编码的文字,那就是“好”;如果它是 UTF16LE编码的文字,那就是“쎺”;如果它是 UTF16LE编码的文字,那就是“뫃”;如果它是uint16_t,那就是 50106;如果它是int16_t,那就是 -15430;……
再再打个比方,你在墙上发现了有人画了3竖,你能确定它表示什么意义吗?小明是个程序员,喜欢二进制值,这3竖表示7;小红是个小学生,刚学会计数,这3竖表示111;小刚是个文盲,这3竖表示3;小喵是只猫,这3竖表示它爪子很锋利;……
同理,对于内存中的 0x00 0x80 0xF6 0x42 这四个字节,float 认为它是 123.25f;int32_t 认为它是 1123450880

long ua    { 1000 };
long long uptr    { (long long) ua };
std::cout << uptr;
这段代码就相当于 中国人打了三只鹿,一个土著人看到了后,在墙壁上刻下「阿巴拉阿巴拉 X0 噶狗」,中国人不需要知道土著人怎么写3,土著人也不需要知道中国人怎么写3

long ua    { 1000 };
long long* uptr    { (long long*)&ua };
std::cout << *uptr;
这段代码就相当于 中国人拿到了土著人的「阿巴拉阿巴拉 X0 噶狗」这块石雕,但他被强迫认为这是中文进行解读,于是中国人解读它为「一个结巴酒喝多了,被伟大的狗神带上了天」
2023-03-30 16:54
后卿
Rank: 4
来 自:网络
等 级:业余侠客
威 望:1
帖 子:302
专家分:295
注 册:2016-10-22
收藏
得分:0 
回复 7楼 rjsp
好的,非常感谢您的解答
2023-03-30 19:17
快速回复:请问指针类型转换和强制类型转换的区别在哪里呢
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.104430 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved