【问题标题】:Dereferencing and typecasting解引用和类型转换
【发布时间】:2011-03-08 14:13:07
【问题描述】:

我构建了以下代码部分来帮助自己理解 C 中的指针解引用和类型转换。

char a = 'a';
char * b = &a;
int i = (int) *b;

对于上述内容,我知道在第 3 行,我取消了 b 的引用并得到了“a”,并且 (int) 将“a”的值类型转换为存储到 i 中的相应值 97。但是对于这部分代码:

char a = 'a';
char * b = &a;
int i = *(int *)b;

这导致 i 是一个任意大的数字,例如 792351。我假设这是一个内存地址,但我的问题是为什么?当我将 b 类型转换为整数指针时,这实际上会导致 b 指向内存中的不同区域吗?怎么回事?

编辑:如果上述方法不起作用,那么为什么这样的事情会起作用:

char a = 'a';
void * b = &a;
char c = *(char *)b;

这会正确地将 'a' 分配给 c。

【问题讨论】:

    标签: c pointers casting


    【解决方案1】:

    您的int 大于您的char - 您将获得'a' 值 + 内存中跟随它的一些随机数据。

    例如,假设内存中的这种布局:

    'a'
    0xFF
    0xFF
    0xFF
    

    您的char *int * 都指向'a'。当您取消引用char * 时,您只会得到第一个字节,即'a'。当您取消引用 int *(假设您的 int 是 32 位)时,您会得到 'a' 和 3 个字节的未初始化数据

    编辑:针对更新的问题:

    char c = *(char *)b; 中,b 仍然指向'a' 值。您将其转换为char *,然后取消引用它,得到char * 指向的字符

    【讨论】:

      【解决方案2】:

      您关心的最后一行做了一件非常糟糕的事情。首先,它将 b 视为 int* 而 b 是 char*。也就是说,b 指向的内存指针被假定为 4 个字节(通常)而不是 1 个字节。因此,当您取消引用它时,它会转到实际 b 指向的 1 个字节,也采用以下 3 个字节,将这 4 个字节视为单个 int,并为您提供结果。这就是为什么它是垃圾。

      一般来说,将一种指针类型转换为另一种指针类型必须非常小心。

      【讨论】:

        【解决方案3】:

        您正在将 char 指针转换为 int 指针。字符(通常)存储为 8 位。另一方面,ints 是 32 位(或 64 位系统上的 64 位)。因此,如果您查看 8 位 b 旁边的其他 24 位内存,您会得到一堆未初始化的额外位。甚至*bi 中的位置也取决于架构。

        big-endian:    **** ****|**** ****|**** ****|0110 0001
        little-endian: 0110 0001|**** ****|**** ****|**** ****
        

        当你投射上面存储的字符时,所有的星号都变得相关。

        【讨论】:

          【解决方案4】:

          由于 char 的长度为 1 字节,而 int 的长度为 4,因此当您从单个字符的地址读取 int 时,您正在读取该字符和另外 3 个字节。这些字节的内容恰好位于内存中(指针,b 的值),甚至可能未分配(导致分段错误)。

          【讨论】:

            【解决方案5】:

            当你将它类型转换为 (int *) 类型时,它将引用内存中的总共 4 个字节(大小 if int)。

            【讨论】:

              【解决方案6】:

              在第二种情况下,您将相同的地址视为指向一个 int。正式地,结果只是未定义的行为。

              实际上,发生的情况是,从该地址开始的四个1 字节中的任何内容都会被解释为 int。

              1 4 个字节,假设是 32 位 int - 如果您的实现有,例如,一个 64 位 int,它将是 8 个字节。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-08-31
                • 1970-01-01
                • 1970-01-01
                • 2012-09-29
                • 2012-02-12
                相关资源
                最近更新 更多