我在一次采访中遇到了这个代码。
int main()
{
int **p;
p = (int **) new int(7);
cout<<*p;
return 0;
}
我期待在 *p 出现一些运行时错误。但是当我运行代码时,它成功执行并输出“0x7”。有人可以解释一下这是如何工作的。谢谢。
除非给你一些额外的限制,否则正确的答案是以上都不是。基本上,代码正在分配一个int
并解释该内存,就好像它是一个int*
(通过一个reinterpret_cast
)。第一个问题是,作为 a reinterpret_cast
,结果在一般情况下是未指定的,并且如果 的大小int
小于int*
(认为是 64 位架构)的大小,则结果是未定义的行为,因为您正在读取超出分配的大小new
称呼。
您创建一个新的 int 并将其初始化为值 7。
int *x = new int(7);
您比将其转换为指针(例如内存地址 7 或 0x07)
int **p = (int**) new int(7);
然后你用 cout 显示这个地址。
*p is equal to (int*)7
它是一个值为 7 的指针。
new int(7);
int
为其值为 is的 an 分配内存7
并返回指向它的指针。
int **p = (int **) new int(7);
告诉编译器将该内存解释为int**
.
cout << *p;
告诉编译器在地址*p
处是一个int *
并且输出它的值。值为0x07
。(它将 int7
视为地址)。额外的取消引用会导致崩溃(准确地说,是未定义的行为)。
int main()
{
int **p; // declare pointer to pointer called p
p = (int **) new int(7); // new allocates integer initialized to value of 7 and returns a pointer. Cast the pointer to a point to pointer. p now represents a pointer to a pointer with contents of 0x7. If you called **p you would get the contents at address 0x7.
cout << *p; // dereference p, this yields a pointer, which is an int of value 0x7.
}
这个问题很可能是为了测试您对指针的了解,但似乎不太实用。
int main()
{
int **p = (int **) new int(7);
cout << *p;
}
因此,new int(7)
分配sizeof(int)
内存字节并返回指向它的指针。假设内存恰好位于地址 X。然后 X 被强制转换(int**)
并存储在p
.
*p
取消引用int**
,这意味着它将int
地址处的值 7 解释X
为int*
.
如果sizeof(int*)
大于sizeof(int)
,则作为 anint*
读取将超出分配的缓冲区new
- 无论数据类型和任何重新解释如何,总是未定义的行为。
如果大小相同,CPU 将尝试读取包含整数 7 的内存int*
- 这通常会产生 value int*(7)
,但查看标准 5.2.10.5:
整数类型或枚举类型的值可以显式转换为指针。* [脚注:转换值为 0 的整数常量表达式 (expr.const) 始终会生成空指针 (conv.ptr),但会转换发生的其他表达式具有零值不需要产生空指针。--- end foonote] 转换为足够大小的整数(如果实现中存在这样的整数)并返回相同指针类型的指针将具有其原始值;指针和整数之间的映射是由实现定义的。
因此,整数值保证转换为某个指针值 - 没有未定义的 - 但该值是实现定义的。尽管如此,作为一个可逆操作, 7 极有可能int
产生一个int*
值为 7 的值——这解释了观察到的输出“7”的行为。
int
大小,它将读取int
值的一部分并将其解释为指针。根据字节顺序,切片可能是 0 或 7 甚至是其他值,但同样,int
它必须可转换为将显示的某个指针值。