2015-10-27 171 views
4

我以爲我有一個指針體面的知識,直到我決定審查一些所謂的微不足道的例子。字符指針vs數組指針

有一件事我知道的是,聲明數組時說:

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

將字符數組作爲字符串輸出非常常見,因此存在一個<< const char * *的重載,它可以幫您實現。實際上沒有人希望在沒有特殊格式的情況下輸出一個int數組,甚至那麼「怎麼知道何時停止?用char數組,0終止字符串,但0只是int數組中的另一個數字。 – user4581301

+0

謝謝大家! – Bobby

回答

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*這個簡單的例子。

0

我認爲這與operator <<有關char*int*比什麼都重要。 C程序員習慣於將null結束的字符串打印出來,所以創建了一個方法來打印它們。可以直接打印int。 A char將無法​​打印出整個字符串。

2

我爲什麼可以打印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*表示的空終止字符串進行例外。處理字符串時,空字符('\0')充當標記字符串結尾的標記值。其他類型沒有這種價值。因此,int*不能被視爲相同的是char*

1

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

然而,這是非常危險的,因爲大多數整數數組不是由零終止,而不是所有指向整數的指針都是數組。

+0

C不使用char *來存儲*字符串。它使用'char *'來*指向*一個字符串。 –

+0

所以'如果(* arr)'如果有值,則評估爲'真';否則爲'假'。有趣。因此,我可以使用'while循環',而不是通常的'for循環'來打印(或manupulate idividual元素)數組'for(int i = 0,i Bobby

+0

@Bobby:只有最後一個元素爲0時纔有效。:-) – Florian