我想看看在下面一行更深:爲什麼我們要將字符串存儲在字符指針中,例如fopen();?
char* filename="file.txt";
這是我做的,當我們使用fopen()
;
我的問題是:
filename
應該持有一個字符的地址(在酷睿2 36位)。爲什麼我們要在其中放置'字符串'?爲什麼編譯器不會生成錯誤,因爲您可能正在存儲一個永遠不會存在的地址?
我想看看在下面一行更深:爲什麼我們要將字符串存儲在字符指針中,例如fopen();?
char* filename="file.txt";
這是我做的,當我們使用fopen()
;
我的問題是:
filename
應該持有一個字符的地址(在酷睿2 36位)。爲什麼我們要在其中放置'字符串'?
爲什麼編譯器不會生成錯誤,因爲您可能正在存儲一個永遠不會存在的地址?
文件名應該保持一個字符的地址(酷睿2 36位),爲什麼我們都在上面放一個「字符串」?
可悲的事實是,我們不是。我們把一個指向字符串文字的第一個字符的指針放在它裏面。字符串"file.txt"
的類型爲char[9]
,當分配給指針時,該字符串衰減爲char *
。但是你應該將它分配給指向const char
的指針,因爲修改它是非法的(導致未定義的行爲)。 Read this.
爲什麼編譯器不會產生錯誤,因爲您可能正在存儲一個永遠不會存在的地址?
不好意思,但是你說什麼樣的地址不存在?字符串文字中第一個字符的地址始終是明確有效的! (但即使它是 - 編譯器知道的語義很少,如果有的話),如果有可能使用一個無效的指針,它根本不可能總是警告你。當然,有時它可以,但是不管怎樣, t有很高的期望。)
請閱讀一些很好的C編程書籍,他們解釋了什麼是指針和數組。
字符串文字像"file.txt"
是char[]
陣列(但你應該把它看成const char[]
因爲像"abc"[1]='D';
內分配字符串文字是undefined behavior有不好的味道,和gcc -Wall
會警告你)。數組可以(通常)被理解爲指向其第一個單元格(索引爲0)的指針 - 換句話說,數組被衰減爲指針 - 因此,您可以將字符串文字分配給指針char
。
但是,數組不是C中的指針;例如sizeof
某些數組是每個元素大小的合適倍數,特別是sizeof("abcde") == 6
(因爲每個字符串文字中都有終止空字節)。但是一些指針與指向區域的大小無關,並且在大多數系統中,所有指針都具有相同的大小,即機器字的大小。
您需要明確地向編譯器詢問所有警告(例如,Linux上的gcc -Wall
)以獲取它們。
首先''file.txt「不是'const char []',它是'char [9]'。其次數組不是指針。他們是他們自己的類型。然而,它們可以腐爛成指針。 – Wiz
我寫了「數組可以理解爲指針」而不是「數組是指針」,並且你不能寫''abc'[1] ='D';'因爲它是一個const char []'而不是'char [ ]' –
@Wiz然而,你可能想與[這個人]交談(http://stackoverflow.com/questions/17604952/convert-int-to-int-pointers-address#comment25624644_17604991)。 – 2013-07-13 06:01:29
文件名應該保存一個字符的地址(core2Duo中的36位),爲什麼我們要在其中放入一個「字符串」?
表達式char* filename="file.txt";
是一個有效的表達式。原因是C中字符串文字的類型爲char[N]
,很容易衰減爲char*
,而char[N]
和char*
是兼容的。因此,您可以將字符串地址分配給char*
指針變量,就像您在此表達式中所做的那樣。
爲什麼編譯器不會產生錯誤,因爲您可能正在存儲一個永遠不會存在的地址?
請閱讀以下三點:
沒有,在表達char* filename="file.txt";
,filename
被分配一個有效的地址。它的概念是這樣(假設地址以21開頭):
filename 21 22 23 24 25 26 27 28 29
+---+ +------------------------------------+
|21 |---> |'f'|'i'|'l'|'e'|'.'|'t'|'x'|'t'|'\0'|
+---+ +------------------------------------+
filename pointing to string, a valid address.
和它不提供任何錯誤或警告:試試下面的代碼示例:
例如-1:
#include<stdio.h>
int main(int argc, char **argv){
char* filename = "filename.txt";
printf("%s", filename);
return 0;
}
編譯:
:~$ gcc y.c -Wall -pedantic
~$ ./a.out
filename.txt
沒有錯誤和戰爭中g,編譯和執行完美。
關於你我的回答評論:
字符串中C
是有點複雜的數據結構則簡單的數值變量,如int
,char
,float
。
在基本數據類型的情況:
int i = 5; You are assigning value 5, to variable i char c = 'A'; You are assigning value 'A' to char variable c. float f = 5.5f; You are assigning value 5.5f to float variable f.
但對於字符串,當你這樣做:字符串"filename.txt"
的
char* filename = "filename.txt";
那麼你實際上是在指定地址爲char *指針變量filename
。
而如果你這樣做:
char filename[] = "filename.txt";
// ^notice [] in declaration
然後要指定字符串「文件名。TXT「;爲CHAR filename[]
的數組,這裏filename
類型爲char[]
要了解雙方的聲明更deferences閱讀:What does sizeof(&arr) return?
字符串文字可以給你你用什麼上下文值或地址的依賴性。 。它例如嘗試:printf(" address: %p, value: %s", "Hello", "Hello");
編譯器不負責驗證地址是否合法。編譯器移植代碼並檢查語法錯誤(例如不可編譯的類型不匹配)。假設你給一個指針指定了一個僞地址,它不會給你一個戰鬥(如果你輸入的是正確的地址)。考慮下面的例子:
例如-2:
#include<stdio.h>
int main(int argc, char **argv){
char* filename = "filename.txt";
char* ptr = (char*)0x020202;
printf("%s %s\n", filename, ptr);
return 0;
}
編譯:
$ gcc y.c -Wall -pedantic
,也不會產生任何誤差或韋林氏。因爲語法上所有都很好而且有效。
(而ptr
分配了一個可能不存在的假地址)。
嗯,其優良的編譯,其中ptr
分配AA假地址例如-2代碼和編譯器不產生任何錯誤/警告,甚至用棍子檢查標誌選項:-Wall -pedantic
。
但是執行此代碼是錯誤的。它試圖在printf語句中訪問分配給ptr
的內存地址,並且該程序將表現異常(在不同的執行實例中)。在C
- 它的語言標準叫做:Undefined behavior。
執行此代碼時OS(但不是編譯器)檢測到進程違反內存權限 - 無效訪問有效內存時出現:SIGSEGV並訪問無效地址時出現:SIGBUS。這可能會導致進程終止/崩潰,並出現一些分段錯誤和coredump。
要了解並瞭解訪問非法內存時可能發生的情況,請閱讀:strcat() implementation works but causes a core dump at the end。
關於你的觀點:」因此你可以把字符串地址分配給char *「,但是我分配字符串而不是字符串地址。地址應該有& – Manzer
@Manzer當你將''filename.txt''分配給'filename'時,你實際上是將字符串''filename.txt'的地址分配給指針。 –
@Manzer在字符串位複雜的數據結構中,然後當你做'i = 4'或'c ='A''時,你需要'char','int',你正在賦值,但是當你做'char * ptr =「hello」'的時候,你正在分配地址, 'char str [] =「hello」;'你正在分配值 –
fopen
進行調用。我認爲地址和字符串是不同的,地址只能是固定的值,而字符串可以是任何東西,所以filename需要一個有效的物理地址,傳遞任何任意字符串。會你介意給一些更多的解釋?在此先感謝那 – Manzer
@Manzer是的,它是持有一個地址,嘗試打印:'printf(「地址:%p,值:%s」,「你好」,「你好」);'一個字符串返回什麼你想要什麼。這取決於你想要的。 –
@Manzer字符串可以是任何東西......在一系列連續的地址處。 – cwallenpoole
請一般閱讀指針和C語言的入門知識。 –
'core2duo中的36位'這些不是您將在C編程中看到的位。 –
由於缺乏對該主題的最低限度知識而投票結束。 SO不能代替基礎教育。 –