簡體   English   中英

C樣式字符串,指針,數組

[英]C style strings, Pointers, arrays

我無法理解C風格的字符串是什么。 新年快樂

我所知道的:指針包含一個內存地址。 取消引用指針將為您提供該內存位置的數據。

int x = 50;
int* ptr = &x;    //pointer to an integer, holds memory address of x

cout << "&x: " << &x << endl;  //these two lines give the same output as expected
cout << "ptr: " << ptr << endl;

cout << "*ptr: " << dec << (*ptr) << endl;  //prints out decimal number 50
                                           //added dec, so the program doesnt 
                //continue to printout hexidecimal numbers like it did for the 
                 //the memory addresses above
cout << "&ptr: " << &ptr << endl;  //shows that a pointer, like any variable,
                                  //has its own memory address

現在我不明白(使用上面的內容作為我的困惑的來源):有多種方式來聲明字符串。 我正在學習C ++,但你也可以使用C風格的字符串(很好理解,雖然不如C ++字符串)

C ++:

string intro = "Hello world!"; 
//the compiler will automatically add a null character, \0, so you don't have to
//worry about declaring an array and putting a line into it that is bigger than 
//it can hold. 

C-風格:

char version1[7] = {'H','i',' ','y','o','u','\0'};
char version2[] = "Hi you"; //using quotes, don't need null character? added for you?
char* version3 = "Hi you";

版本3是我遇到麻煩的地方。 這里有一個指向char的指針。 我知道數組名是指向數組中第一個元素的指針。

cout << " &version3: " << &version3 << endl; //prints out location of 'H'
cout << " *version3: " << *version3 << endl; //prints out 'H'
cout << "  version3: " <<  version3 << endl; //prints out the whole string up to
                                             //automatically inserted \0

之前,在“我所知道的”部分中,打印出指針的名稱會打印出它所持有的地址。 在這里,打印出指針的名稱會打印出整個字符串。 圍繞“嗨你”的雙引號會以某種方式告訴程序:“嘿,我知道你是一個指針,你被初始化為'H'的位置,但因為我看到這些雙引號,在內存位置向前跳過1個字節並打印出你看到的所有內容,直到達到\\ 0“(1字節移動,因為字符大1字節)。

如何打印出一個指針打印出一個字符串? 在打印出一個指針名稱之前,打印出它被初始化為的內存地址。

編輯: cout << &version3是否打印出'H'的位置或指針的位置, version3 ,其中包含內存地址'H'?

使用cout打印char*工作方式與打印不同,例如,帶有coutint* 為了與C風格的字符串兼容,帶有char*參數的<<的重載版本將char*視為C風格的字符串。 如果要打印char*所持有的內存地址,可以將其轉換為void*

是的,如果你寫任何一個

char *s1 = "hi lol";
char s2[] = "hi haha";

在字符串的末尾為您添加NUL( \\0 )終結符。 這兩者之間的區別在於s1是指向字符串文字的指針,根據C標准,您不應該修改內容,而s2是一個數組 ,即為您分配的內存塊堆棧, 初始化為保存值"hi haha" ,您可以隨意修改其內容。 為數組分配的內存量足以保存用作初始化程序的字符串,並自動為您確定,這就是方括號可以為空的原因。

一面注意:在C中,如果輸入char s[3] = "abc"; ,然后s將初始化為{'a', 'b', 'c'}沒有 NUL終止符! 這是因為標准中的一個子句說如果數組中有空間 (或類似的措辭),則使用NUL終結符初始化此上下文中的字符串。 在C ++中,情況並非如此。 有關更多信息,請參閱初始化固定大小的char數組時沒有編譯器錯誤,但沒有足夠的空間用於null終止符

編輯,以回應您添加的問題:如果您有char *s = "..." ,並且你cout << &s; ,它將打印存儲指針 s的地址,而不是s保存的地址( s引用的字符串的第一個元素的地址)。

我知道數組名是指向數組中第一個元素的指針。

不,不是。 它只會隱式轉換為一個(在大多數情況下)。

圍繞“嗨你”的雙引號會以某種方式告訴程序:“嘿,我知道你是一個指針,你被初始化為'H'的位置,但因為我看到這些雙引號,在內存位置向前跳過1個字節打印出你看到的一切,直到你達到\\ 0“?

不,他們沒有。 這是重要的類型。

std::ostream::operator<<具有用於通用指針的過載( void *過載const char * 所以當你寫cout << "some char array or pointer"; ,它將調用該重載,而不是其他指針類型的重載。 這種重載的行為有所不同:它不是打印指針的數值,而是打印出所有內容,直到NUL終止符。

你在這里問兩個問題,其中一個問題比較籠統,我將首先回答。

指針是指向內存中某個位置的“句柄”(稱為地址)。 該位置的內容是一個值。 如何解釋該值取決於指針的“類型”。 可以這樣想:地址是房子的位置,例如10 Main Street。 10 Main Street的內容是該地址的房子內容。 在C(和C ++)術語中:

int *p;

是一個可以保存整數地址的變量。

int x;

是一個整數的變量。

p = &x;

通過在p中存儲x的ADDRESS,p'指向'x。

x = 10;

在x中存儲值10。

*p == x

因為* p表示'使用p'的內容作為值,然后將其與x進行比較。

p == &x

因為&x表示'使用x的地址'作為值,然后將其與p進行比較,p是類型指針的變量。

字符串是零個或多個字符的序列,在C(和C ++)中用字符“和”表示。 在內存中,這些值是連續存儲的,並由一個尾隨的空字節自動終止,該字節是一個值為0的字節。字符串“Hello,world!” 假設您使用的是8位ASCII字符編碼,則存儲在內存中,如下所示:

65 101 108 108 111 44​​ 32 87 111 114 108 33 0

您可以使用以下代碼段自行查看:

char *p = "Hello, World!";
int len = strlen(p);
int i;

for (i = 0; i <= len;  ++i)
{
    std::cout << std::dec << (int) p[i] << ' ';
}
std::cout << std::endl;

由於null(零字節)由編譯器自動添加到常量字符串,因此以下兩個數組的大小相同:

char a1[7] = { 'H', 'i', ' ', 'y', 'o', 'u', '\0' };
char a2[] = "Hi you";

std::cout << strcmp(a1, a2) << std::endl

簡單地說,'C樣式字符串'只是一個以null結尾的字符數組,它可以回答您的第一個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM