我认为我对指针有了不错的了解,直到我决定回顾一些所谓的琐碎的例子。
我知道的一件事是,在声明一个数组时说:
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";
}
答案 0 :(得分:9)
当您流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*
只是一个特例。
答案 1 :(得分:2)
为什么我可以打印
#include <iostream> #include <vector> #include <algorithm> #include <iterator> using namespace std; int main() { vector<int> nonprimi; vector<int> primi; for (int i = 0; i < 100; i++) { nonprimi.push_back(i); } for (int i = 0; i < nonprimi.size(); i++) { if (((nonprimi[i] == 2) || (nonprimi[i] == 3) || (nonprimi[i] == 5) || (nonprimi[i] == 7)) || (nonprimi[i] % 2 != 0) && (nonprimi[i] % 3 != 0) && (nonprimi[i] % 5 != 0) && (nonprimi[i] % 7 != 0)) { primi.push_back(i); } } for (int i = 0; i < primi.size(); i++) { cout << primi[i] << " "; } // or in a more STL way // copy(primi.begin(), primi.end(), ostream_iterator<int>(cout, " ")); // system("pause"); return 0; }
并将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*
类型的指针时,会调用第一个。第二个用于tpe char const*
或char*
的所有指针。第二个输出一直到终止空字符,而第一个输出指针值。
这解释了输出。
理解为什么标准库以不同方式对待它们具有指导意义。
语言和标准库对由char const*
和char*
表示的空终止字符串进行例外处理。处理字符串时,空字符(char const*
)充当标记字符串结尾的标记值。其他类型没有这样的价值。因此,'\0'
无法对int*
进行处理。
答案 2 :(得分:1)
char*
可能很特殊,因为C决定用它来表示字符串。在这种情况下,char*
引用空终止的字符数组,即C-string。您可以打印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";
}
然而,这是非常危险的,因为大多数整数数组不是以零结尾,而且并非所有指向整数的指针都是数组。
答案 3 :(得分:0)
我认为这与operator <<
和char*
的{{1}}有关。 C程序员用于将终止的字符串打印出来,因此创建了一个方法来打印它们。 int*
可以直接打印。 int
将无法打印出整个字符串。