編輯:(編輯問題,以便我盡可能準確)我試圖對下面的陳述句發生的事情有一個基本的了解。正如您在評論中看到的那樣,SO 社區中的程式員/軟體工程師似乎對此存在分歧。
宣告很簡單,如下:
char* str = "Hello world";
根據我的 CS 教授的說法,參考上述宣告,他說......
“這是危險的(并且在 C 標準中正式棄用),因為您還沒有為 str1 分配記憶體指向。”
首先,我知道它已被棄用,我不應該使用它——這很清楚。
我遇到的問題是,我顯然不明白上面陳述句中的記憶體分配是如何發生的,或者說“我不明白記憶體分配在哪里發生”可能更準確。似乎沒有分配堆中的記憶體,堆疊應該作為 LIFO 概念型別的記憶體作業,這意味著您不會在堆疊記憶體儲字串,這就是我迷路的地方。如果"Hello World"沒有存盤在堆上,或者在堆疊中,它存在于哪里?str如果指標不指向堆,指標指向哪里?看,我從根本上錯過了一些東西。
“我不知道如何比這更清楚。”
uj5u.com熱心網友回復:
[免責宣告:當問題被標記為 [c] 和 [c ] 時,我寫了這個答案。C 和 C 的答案肯定不同。在這個答案中,我有點傾向于 C。]
char* str = "Hello world";
這在 C 中完全沒問題。
根據我的 CS 教授的說法,參考上述宣告,他說......
“這是危險的(并且在 C 標準中正式棄用),因為您還沒有分配記憶體
str來指向。”
要么你誤解了,要么你的教授非常困惑。
該代碼在 C 中已被棄用,因為您忽略了將其宣告str為指向不可修改(即const)字符的指標。但是,指向字串的分配沒有任何問題,絕對沒有問題。
當你寫
char *str = "Hello world";
編譯器負責為strto分配記憶體。編譯器的行為或多或少就像你寫的一樣
static char __hidden_string[] = "Hello world";
char *str = __hidden_string;
或者可能
static const char __hidden_string[] = "Hello world";
char *str = (char *)__hidden_string;
現在,該__hidden_string陣列分配在哪里?當然不在堆疊上(你會注意到它被宣告了static),當然也不在堆上。
曾幾何時,__hidden_string陣列通常與(大部分)其余全域變數一起分配在“初始化資料”段中。這意味著您可以隨意修改它,如果您愿意的話。
__hidden_string如今,一些/許多/大多數編譯器分配在不可寫的段中,甚至可能是代碼段。在這種情況下,如果您嘗試修改字串,則會出現總線錯誤或類似錯誤。
出于向后兼容性的原因,C 編譯器不能將字串常量視為型別為const char []。如果他們這樣做了,你會在寫的時候收到警告
char *str = "Hello world";
在某種程度上,警告會是一件好事,因為它會迫使你寫
const char *str = "Hello world";
明確str指出您不允許修改的字串。
但是 C 沒有采用這個規則,因為它會破壞太多舊代碼。
另一方面,C 已經或正在采用此規則的某個版本。當我char *str = "Hello world";在兩個不同的 C 編譯器下嘗試時,我得到warning: conversion from string literal to 'char *' is deprecated. 這很可能就是你的教授想要達到的。
uj5u.com熱心網友回復:
概括:
"any strings in double quotes"areconst lvalue string literals,存盤在已編譯程式中的某處。你不能修改這樣的字串,但你可以存盤指向這個字串的指標(當然是const)并在不修改的情況下使用它:
const char *str = "some string"例如:
int my_strcmp(const char *str1, const char *str2) { ... } int main() { ... const char *rule2_str= "rule2"; // compare some strings if (my_strcmp(my_string, "rule1") == 0) std::cout << "Execute rule1" << std::endl; else if (my_strcmp(my_string, rule2_str) == 0) std::cout << "Execute rule2" << std::endl; ... }如果您想修改字串,您可以將字串文字復制到您自己的陣列:
char array[] = "12323",然后您的陣列將初始化為字串,并在末尾終止零:其實
char array[] = "123"是一樣的char array[] = {'1', '2', '3', '\0'}。例如:
int main() { char my_string[] = "12345"; my_string[0] = 5; // correct! std::cout << my_string << std::endl; // 52345 }請記住,您的陣列將是靜態的,因此您無法更改它的大小,對于“動態大小”字串使用
std::string.
uj5u.com熱心網友回復:
問題出在lvalue和rvalue。lvalue定義定位器值,這意味著它在記憶體中具有指定的位置,您可以輕松獲取它。rvalue在記憶體中有未定義的位置。例如, anyint a = 5具有5as rvalue。所以你不能取 rvalue 的地址。當您嘗試char* str = "Hello World"使用類似的東西訪問記憶體時,str[0] = 'x'您將收到錯誤訊息Segmentation fault,這意味著您試圖獲得無法使用的記憶體。順便說一句,運算子*和&被禁止rvalues,如果您嘗試使用它們,它會引發編譯時錯誤。
所述lvalue的"Hello World"被存盤在存盤器的programms的段。但它是這樣指定的,因為程式不能直接修改它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/315010.html
下一篇:函式作用域和指標
