Re: [問題] 關於記憶體位置和記億體位置之值

看板C_and_CPP (C/C++)作者 (葉酸酸)時間15年前 (2010/11/24 21:14), 編輯推噓6(607)
留言13則, 5人參與, 最新討論串2/2 (看更多)
※ 引述《g56 (GG5566)》之銘言: : 遇到的問題: (題意請描述清楚) : 各位大大好 : char string[]="Input an integer"; : int p1=(int) &string; : // p1設定成為string的記憶體所在位置的值 : printf("%s\n",p1); : // ^^這樣寫同樣可以印出字串string : -------------------------- : 以上為程式碼, : 但小弟我一直無法接收p1印出來為字串, : 因為這行 int p1=(int) &string; 的意思是把string的記憶體位置值傳給p1 : 所以p1應該是為記億體位置而不是字串.. : 謝謝您看完這個問題...<(_ _)> : 希望得到的正確結果: : p1為記憶體位置 : 開發平台: (例: VC++ or gcc/g++ or Dev-C++, Windows or Linux) : windows : 有問題的code: (請善用置底文標色功能) : p1=(int) &string; : 不是記憶體位置 char string[] = "input an integer"; 這行的意思是定義一個 char array,string 是 identifier。 ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ │ i│ n│ p│ u│ t│ │ a│ n│ │ i│ n│ t│ e│ g│ e│ r│\0│ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ ↖ 這是一個記憶體的位置,假設是 00000000,所以後面可以類推,如下圖 ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ │ i│ n│ p│ u│ t│ │ a│ n│ │ i│ n│ t│ e│ g│ e│ r│\0│ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ ↖ ↖ ↖ ↖ ╲ ╲ ╲ 00000003 ╲ ╲ 00000002 ╲ 00000001 00000000 然後 00000000 這個 value 放在一個叫做 string 的變數裡面。 ┌────┐ │00000000│ └────┘ string 我們一個一個看 int p1=(int) &string; &string 拿到 00000000 (int) 把 00000000 這個 value 的 type 從 address 轉換成一個 int, 所以 p1 的 value 會變成 00000000。 然後 printf("%s\n",p1); p1 是一個 int,而 %s 要求的是一個 pointer,型別不合。 所以你要改成 (char *) p1,這樣會變成一個 address 也就是 00000000 所以最後 printf("%s\n", (char *) p1); 會得到你要的結果。 不過與其這樣,你不如寫: char string[] = "Input an integer"; char *pointer = string; printf("%s\n", pointer); 啊只是你這樣 pointer 跟 string 這兩個 identifier 的 value 都是同一個 address 就是了,這又叫做 shallow copy,或淺 copy。 因為你透過 string 這個 identifier 做的任何事情, 透過 pointer 也會發現一樣的改變。 如果要真正產生兩個獨立的個體,你需要給 pointer 一個位置,最簡單的方法如下。 char string = "Input an integer"; char array[30]; char *pointer = array; int counter; for (counter = 0; counter < 17; counter++) *(pointer + counter) = string[counter]; 像這樣透過 for loop 慢慢一個一個 copy,才可以確實做出兩個獨立的個體。 相對於 shallow copy,這叫做 deep copy。 那 counter < 17 這裡的條件式其實可以寫成 counter < strlen(string) + 1 strlen 這個 function 放在 string.h 這個 header file 裡面。 然後 + 1 是要連 string 結尾的 \0 一起算進去。 不過這樣等於每次做 forloop 的時候都要執行一次 strlen(),考慮到效能, 最好宣告一個 int limit = strlen(string); 然後改寫成 counter < limit 比較有效能。 然後我們這裡配置記憶體給 pointer 的方式是由程式設計師靜態宣告一個 arry。 這樣很不方便,其實我們可以改成用 malloc 這個函式動態宣告,我們可以這樣寫。 malloc(limit) 這樣寫是可以的,只是習慣不太好。 為什麼這樣說呢?因為在這裡因為是 char 的關係,所以只有 1 byte,剛好沒問題。 如果是 int 以 32 bit compiler 來說 int 是 4 個 byte,所以就是要 limit * 4。 那這樣寫還是不太好,因為有的 compiler 的 int 只有 16 bits,就是 limit * 2, 那到底要寫 4 還是 2?很簡單我們只要寫 limit * sizeof (int) 就會幫我們抓。 sizeof (int) 會依據系統的關係,抓到 (int) 所需要的大小。 所以我們寫 malloc( limit * sizeof (int) ) 啊不過 malloc 傳回來的 data type 是 void *,而我們宣告的 pointer type 是 char *,所以要做 type casting。 (char *) malloc ( limit * sizeof (int) ) 結果就是 char *pointer = (char *) malloc ( limit * sizeof (int) ); 所以我們最後這樣寫。 #include <string.h> int main(void) { char string[] = "Input an array"; int limit = strlen(string) + 1; char *pointer = (char *) malloc( limit * sizeof (int) ); int counter; for (counter = 0; counter < limit; counter++) *(pointer + counter) = string[counter]; return 0; } 啊不過這裡 *(pointer + counter) 的寫法有點拖泥帶水,可以直接寫成: pointer[counter]。 也就是改成: pointer[counter] = string[counter]; 啊不過以上 for loop 的部份其實有些好的 function 可以用,叫 strcpy, 也是放在 string.h 這個 header 裡面。 我們可以寫成下面這樣 int main(void) { char string[] = "Input an integer"; int limit = strlen(string) + 1; char *pointer = (char *) malloc( limit * sizeof (int) ); strcpy(pointer, string); printf("%p = %s; %p = %s\n", string, string, pointer, pointer ); return 0; } 跑看看就知道了。 -- One should love animals. They are so tasty. 每個人都應該愛動物,他們是如此美味。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 123.204.248.250

11/24 21:18, , 1F
雖然你很用心, 但是 string 只是個陣列名字, 不佔空間
11/24 21:18, 1F

11/24 21:20, , 2F
看到圖我嚇了一跳...怎麼大家都這麼會畫
11/24 21:20, 2F

11/24 21:22, , 3F
對我剛剛發現寫錯了orz
11/24 21:22, 3F
※ 編輯: B9 來自: 123.204.248.250 (11/24 21:24)

11/24 21:24, , 4F
後來我發現畫圖+上色賺p幣比較快 XDD
11/24 21:24, 4F

11/24 21:24, , 5F
好用心.....謝謝您
11/24 21:24, 5F

11/24 21:25, , 6F
我現在才知道 char array[]; &array == array orz
11/24 21:25, 6F

11/24 21:30, , 7F

11/24 21:38, , 8F
type 不對,不過 value 一樣 http://codepad.org/25utn5PN
11/24 21:38, 8F

11/24 21:41, , 9F
因為編譯器有偷偷幫你轉...根本不能用"值"來下結論
11/24 21:41, 9F

11/24 21:43, , 10F
嗯對,受教了:)
11/24 21:43, 10F

11/25 07:16, , 11F
第88行 char string = "Input an integer"; 應該是string[]
11/25 07:16, 11F

11/25 14:38, , 12F
其實你用Visaul C++下中斷點,用監視變數功能,就會把變數
11/25 14:38, 12F

11/25 14:38, , 13F
型態還有內容值都顯示出來,不用自己那邊printf或自己猜
11/25 14:38, 13F
文章代碼(AID): #1CxG-kFg (C_and_CPP)
文章代碼(AID): #1CxG-kFg (C_and_CPP)