char buffer[4];
std::cout << &buffer << std::endl;
std::cout << &buffer[0] << std::endl;
当我运行此代码时,第一行是缓冲区中第一个元素的十六进制地址。第二行是四个问号(除非我被转换为空指针)。
第二个陈述与第一个陈述有何不同(从语义上讲,它们是相同的?)? 为什么第二行显示为问号而不是随机垃圾字符?
答案 0 :(得分:7)
&buffer
以适当的指针类型为您提供缓冲区的地址。该类型为char (*)[4]
。
&buffer[0]
为您提供第一个缓冲区元素的地址(char
),因此地址的类型为char*
。
标准流类有一个处理char const*
的重载,但没有处理char (*)[4]
的重载。但是指针有一般的重载,接受void*
。因此,指向数组的指针被隐式转换为void*
,并传递给该重载。因此,您可以看到缓冲区的地址。
在第二种情况下,如果buffer
已正确初始化,您将看到其内容已打印(“c-string”重载的内容)。但是,由于您没有初始化它,因此您的代码具有未定义的行为。仅仅尝试打印缓冲区没有明确的结果。
答案 1 :(得分:4)
&buffer
是缓冲区的地址。 &buffer[0]
是缓冲区中第一个字符的地址。在你的情况下,这是一个垃圾值,因为你没有初始化它。尝试初始化它:
char buffer[] = "Hello there!";
std::cout << &buffer << std::endl;
std::cout << &buffer[0] << std::endl; // print from first element to the end(until the first null-character)
std::cout << &buffer[4] << std::endl; // print from fifth element to the end
输出:
0018FF38
Hello there!
o there!
我认为这是osstream insertion operator <<
的一个问题,它假设你传递一个char*
而你传递给一个角色的地址,所以我猜它是一个UB。
要获取角色的地址,必须将其投射到void*
:
std::cout << static_cast < void* >(&buffer[0]) << std::endl;
std::cout << static_cast < void* >(&buffer[1]) << std::endl;
输出:
0018FF38
0018FF39
要确认它是ostream <<
问题,请尝试使用printf
:
printf("&buffer[0]: %p \n", &buffer[0]);
输出:
&buffer[0]: 0018FF38