0

我有以下代码,在 64 位 linux 上,内核 2.6.x。据我了解,第一个 mallocrrr=malloc(8)在堆上分配 8 个字节,而 rrr 现在包含这 8 个字节的起始地址的值。然后,我做一些疯狂的事情。我尝试将 8 字节指针存储在单个字节中,如*rrr = malloc(8). 然后我在第 5 个字节做同样的事情。单个字节最多只能容纳 255 的值,但是当我打印存储在这些字节中的值时,值大于 255。你能解释一下吗?

#include <stdlib.h>
#include <stdio.h>

void ** rrr;
int main(int argc, char ** argv)
{
  rrr = malloc(8); // rrr should point to the starting address of an 8 byte block
  *rrr = malloc(8);
  *(rrr+5) = malloc(8);

  for(int i =0;i< 8;i++)
    printf("*rrr%d: %p\n", i, *(rrr+i)); // should print what is stored in each byte

 return 0;
}

一次以上回报

*rrr0: 0x9ae030
*rrr1: (nil)
*rrr2: (nil)
*rrr3: 0x21
*rrr4: (nil)
*rrr5: 0x9ae050
*rrr6: (nil)
*rrr7: 0x21
4

3 回答 3

1

我尝试将一个 8 字节指针存储在一个字节中

您的代码中没有单个字节。 rrr是一个指针,所以也是*rrr(因为你声明rrr为一个指向指针的指针)。

但是,您几乎可以肯定在这里调用了未定义的行为。除非sizeof(void *)是 1(这极不可能!),然后写入*(rrr+5)将超出您分配的内存范围。

于 2013-02-09T21:18:42.653 回答
1

单个字节最多只能保存 255 个值,但是当我打印存储在这些字节中的值时,这些值大于 255

但是*rrr是 a void *,它在您的机器上可能是 8 个字节,并且能够根据定义保存任何对象指针。

此外,由于您只为 分配了 8 个字节rrr,因此第一个元素之后的任何内容(分配或读取)都是非法的。


您似乎认为分配 8 个字节会以某种方式在元素之间平均分配它们,但事实并非如此。在分配rrr指向您可以使用的 8 个字节之后,您可以使用*rrr = malloc.... 这一切都是正确的和预期的:*rrr是一个空,因此能够保存任何地址,因此能够保存大于你提到的 255 的东西。

当您走得更远rrr + 1或更远的时候,您就会陷入未定义的行为,并且会发生意想不到的事情。

编辑

但我反驳说,如果我打印一个 8 字节块的每个字节值,那么任何字节都可以保存大于 255 的值

但是你不是在打印字节!您正在打印指针并添加i到将其rrr 推进到下一个指针

于 2013-02-09T21:19:21.033 回答
1

由于rrris a void**rrr+5将 40 字节指向您分配的 8 字节内存,因为 sizeof(void *) == 8在 64 位 linux 机器上。

每当您将整数添加到 C 中的指针时,整数总是按(乘以)指针指向的任何大小(sizeof(*rrr)此处为sizeof(void *)

于 2013-02-09T21:23:45.267 回答