指向字符的指针与指向数组的指针

pointer to char vs pointer to arrays

本文关键字:指针 数组 字符      更新时间:2023-10-16

我以为我对指针有很好的了解,直到我决定复习一些所谓的琐碎例子。

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

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";
}

当您流式传输h时,您正在使用此重载:

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

但是当你流式传输p时,你正在使用这个:

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

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

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

标准库提供了两个用于处理指针的 operator<< 函数重载。

成员函数重载:

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

以及非成员函数重载:

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

cout << ptr 用于所有不属于 char*char const* 类型的指针时,将调用第一个。第二个用于所有具有 tpe char*char const*的指针。第二个输出所有内容,直到终止空字符,而第一个仅输出指针值。

这解释了输出。

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

语言和标准库对由 char*char const* 表示的以 null 结尾的字符串进行了例外。 在处理字符串时,空字符(''(充当标记字符串末尾的哨兵值。对于其他类型没有这样的值。因此,不能像对待char*一样对待int*

在某些情况下

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

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

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

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";
}

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

我认为这与char*operator <<有关,int*比其他任何事情都重要。C 程序员习惯于将以 null 结尾的字符串打印出来,因此创建了一个方法来打印它们。 int可以直接打印。char将无法打印出整个字符串。