为什么print& some_buf [0]和& some_buf给出不同的输出?

时间:2017-08-13 11:25:54

标签: c++ g++

char buffer[4];
std::cout << &buffer << std::endl;
std::cout << &buffer[0] << std::endl;

当我运行此代码时,第一行是缓冲区中第一个元素的十六进制地址。第二行是四个问号(除非我被转换为空指针)。

第二个陈述与第一个陈述有何不同(从语义上讲,它们是相同的?)? 为什么第二行显示为问号而不是随机垃圾字符?

2 个答案:

答案 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