【问题标题】:pointer to char vs pointer to arrays指向 char 的指针与指向数组的指针
【发布时间】:2016-01-27 09:59:05
【问题描述】:

我认为我对指针有相当的了解,直到我决定复习一些所谓的琐碎示例。

我知道的一件事是,在声明数组时说:

int arr[2] {3, 5};

arr 将保存数组中第一个元素的值,因此尝试打印 (cout << arr) 显然会给出arr[0] 的地址。即使认为我的程序使用指针它仍然相似。

我的问题是为什么我可以打印h 并将bonjour 作为输出,但我不能对p 做同样的事情?

看起来当我增加 h++ 并再次打印时,我得到了 onjour。指针与char 有何不同?

#include <iostream>
#include <string>

int main()
{
    char* h = "bonjour";
    int k[4]{3, 4, 5, 6};
    int * p = k;

    std::cout << "Hello, "<< h << "!\n";
}

【问题讨论】:

  • 将字符数组输出为字符串是如此普遍,以至于const char *

标签: c++ pointers char


【解决方案1】:

当您流式传输h 时,您使用的是this overload

template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,  
                                        const char* s );

但是当您流式传输p 时,您使用的是this one

basic_ostream& operator<<( const void* value );

前者将打印每个字节,直到它到达\0,后者将简单地打印地址。也就是说 - 您正在利用 const char* 的一个特殊情况。

【讨论】:

    【解决方案2】:

    我认为这与operator &lt;&lt;char*int* 的关系最重要。 C 程序员习惯于打印出以空结尾的字符串,因此创建了一种方法来打印它们。 ints 可以直接打印。 char 将无法打印出整个字符串。

    【讨论】:

      【解决方案3】:

      为什么我可以打印h 并将bonjour 作为输出而我不能对p 做同样的事情?看起来当我增加h++ 并再次打印时,我得到onjour。指针与char 有何不同?

      标准库提供了operator&lt;&lt; 函数的两个重载来处理指针。

      成员函数重载:

      basic_ostream& operator<<( const void* value );
      

      和一个非成员函数重载:

      template< class Traits >
      basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,  
                                              const char* s );
      

      cout &lt;&lt; ptr 用于所有不是char*char const* 类型的指针时调用第一个。第二个用于所有属于char*char const* 的指针。第二个输出直到终止空字符的所有内容,而第一个只输出指针值。

      这解释了输出。

      了解为什么标准库以不同方式对待它们是很有启发性的。

      语言和标准库对由char*char const* 表示的空终止字符串产生例外。处理字符串时,空字符 ('\0') 充当标记字符串结尾的标记值。其他类型没有这样的价值。因此,int* 不能像 char* 一样对待。

      【讨论】:

        【解决方案4】:

        char* 在某些情况下可能很特殊,因为 C 决定用它来表示字符串。在这种情况下,char* 指的是一个以空字符结尾的字符数组,也就是 C 字符串。您可以打印h 但不能打印p 的原因是因为存在一个对char* 进行特殊处理的函数:

         std::ostream::operator<<(std::ostream& os, const char*);
        

        您可以提供自己的重载来打印以空结尾的整数数组:

        std::ostream& operator<<(std::ostream& os, const int* arr) {
           while (int i = *arr++) {
              os << i;
              if (*arr) os << ", ";
           }
           return os;
        }
        
        int main()
        {
          const int arr[] = {1, 2 ,3, 4, 0};
          std::cout << arr << "\n";
        }
        

        但是,这是非常危险的,因为大多数整数数组都不是以零结尾的,而且并非所有指向整数的指针都是数组。

        【讨论】:

        • C 不使用char*存储 字符串。它使用char* 指向一个字符串。
        • 所以if (*arr) 如果有值则计算为true,否则计算为false?有趣的。因此,代替通常的for loop 来打印(或操作单个元素)数组for (int i=0, i&lt;sizeof(array);),我可以只使用while loop 然后:while((*array)) do somestuff and array++!(?)。
        • @Bobby:只有在最后一个元素为 0 时才有效。:-)
        • @KeithThompson,你说得对。我改了。
        • @Bobby: if (*arr) 本质上等同于if (*arr != 0)。 (在 C 中它完全等价;C++ 运算符重载可能会创造其他机会。)
        猜你喜欢
        • 2018-04-05
        • 2017-09-03
        • 1970-01-01
        • 2021-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-26
        • 1970-01-01
        相关资源
        最近更新 更多