作者x246libra (宸火)
看板C_and_CPP
標題[問題] 字串輸出疑問
時間Fri Nov 3 15:59:05 2017
開發平台(Platform): (Ex: Win10, Linux, ...)
xp
編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出)
code block
問題(Question):
程式碼交換位置後 執行出現錯誤
餵入的資料(Input):
1234
程式碼(Code):(請善用置底文網頁, 記得排版)
#include <stdio.h>
#include <stdlib.h>
main()
{
char str1[]="";
char *str2="您輸入的字串如上";
printf("請輸入字串:");
fgets(str1,80,stdin);
printf("%s",str1);
printf("%s",str2);
}
以上程式碼 執行時 會出現錯誤
------------------------------------------
#include <stdio.h>
#include <stdlib.h>
main()
{
char str1[]="";
printf("請輸入字串:");
fgets(str1,80,stdin);
printf("%s",str1);
char *str2="您輸入的字串如上";
printf("%s",str2);
}
將 char *str2="您輸入的字串如上";
這段移動到下方
就可以正常執行
不明白為什麼
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.220.35.157
※ 文章網址: https://webptt.com/m.aspx?n=bbs/C_and_CPP/M.1509695947.A.7F8.html
1F:→ MOONRAKER: 沒有為什麼,剛好而已。兩段都是錯的。 11/03 16:09
2F:→ x246libra: 我是按照書本練習打的 執行出現錯誤的是書本範例 11/03 16:11
3F:→ x246libra: 我自己移到到下方才可以執行 但是不明白為什麼 11/03 16:11
4F:→ x246libra: 為什麼說兩段都是錯誤的? 11/03 16:12
5F:→ stupid0319: 上面的那個如果輸入超過4BYTE就溢位修改到str2指標了 11/03 16:18
6F:→ stupid0319: str2指標錯誤之後,printf("%s",str2);就掛掉了 11/03 16:19
7F:→ stupid0319: 下面那個是str2指標在printf("%s",str1);後才補上 11/03 16:20
8F:→ stupid0319: 運氣好沒掛點,但是兩段code都是零分XD 11/03 16:21
9F:推 ssdoz2sk: 燒書了(O 11/03 16:25
10F:→ x246libra: 但是我只輸入1234 沒超過4BTYE 還是執行錯誤 11/03 16:26
11F:→ ssdoz2sk: \0 11/03 16:27
12F:→ stupid0319: 你確定是4BYTE? 還是5BYTE,還是6BYTE? 想清楚唷 11/03 16:28
13F:→ stupid0319: 來4,5,6 BYTE選一個 11/03 16:30
14F:→ x246libra: 加上 \0 應該是 5BYTE 吧 11/03 16:33
維持 第一個程式的順序
改為輸入 A
執行不會有錯誤
但是
printf("%s",str2);的功能沒有顯示出來
輸出如下=>
請輸入字串:1
1
---------------------------------------
改為輸入 AB
執行還是有錯誤 當機
這次應該沒超過4 Byte了吧?
為什麼還是有錯誤
※ 編輯: x246libra (61.220.35.157), 11/03/2017 16:45:15
15F:→ stupid0319: 你strlen看看是不含\0幾BYTE, 11/03 16:43
16F:→ stupid0319: 別在玩記憶體溢位了,駭客級別的程式設計太難 11/03 16:51
17F:→ x246libra: 用了strlen 輸入1234 是得到5 11/03 16:53
18F:→ stupid0319: 5是包括\0還是不包括\0呢? 11/03 16:56
19F:→ stupid0319: 或者是包括了什麼特殊字元? 11/03 16:57
main()
{
char str1[]="";
int n;
fgets(str1,80,stdin);
printf("%d",strlen(str1));
}
單純使用 strlen 輸入1234
輸出5
※ 編輯: x246libra (61.220.35.157), 11/03/2017 17:02:37
20F:推 loveflames: strlen是算str1那個字串的長度,要知道陣列不能作為 11/03 17:06
21F:→ loveflames: 函數參數,會decay成指標,然後沒當的原因是你覆蓋的 11/03 17:07
22F:→ loveflames: 只是int 11/03 17:08
stupid0319: 上面的那個如果輸入超過4BYTE就溢位修改到str2指標了
這段話 老實說 我不太懂 不知道是否可以再說明一下
為什麼不可以超過4byte?
程式碼中 fgets(str1,80,stdin); 不是說可以可以使用80個字元嗎?
如果真的4BYTE就溢位 又什麼會修改到str2指標?
他們的記憶體位置有連續嗎?
※ 編輯: x246libra (61.220.35.157), 11/03/2017 17:10:36
23F:→ loveflames: 看起來是32bit環境,那指標是4byte,超過對齊的範圍 11/03 17:25
24F:→ loveflames: 就會覆蓋到後面的 11/03 17:26
25F:→ loveflames: 這些都是undefined行為,研究這麼沒營養的東西幹嘛 11/03 17:27
26F:→ stupid0319: 太難了,str1因記憶體對齊的關係會配到4BYTE 11/03 17:28
請問一下 是因為這句程式 char str1[]="";
所以str1才被配到4Byte嗎?
27F:→ stupid0319: 如果不是想當駭客的話,不要這樣亂寫程式 11/03 17:29
28F:→ loveflames: 我對這個小有涉獵,雖然是很久以前的事 11/03 17:30
只是想瞭解後面的原理 只是個初學者
沒特別想這樣寫程式
※ 編輯: x246libra (61.220.35.157), 11/03/2017 17:32:38
29F:→ stupid0319: 請寫char str1[80] = ""; 11/03 17:30
30F:→ stupid0319: 而fgets會吃到\n,都要算進去,你都沒處理,都沒教? 11/03 17:32
31F:推 stupid0319: char str1[]="";同等於 char str1[1]; strl[0] = '\0' 11/03 17:36
32F:→ loveflames: str2在32bit環境是4byte,str1不到4byte,會對齊成4by 11/03 17:36
33F:→ loveflames: te 11/03 17:36
34F:→ loveflames: 研究這個的原理也是浪費時間 11/03 17:38
謝謝以上的回答 那就不再研究下去了
至少讓我知到了 不到4Byte 會自動對齊到 4Byte
感謝各位的回答
原本也只是好奇 為什麼書本說可以執行 但是我卻不能
沒特別想說要研究記憶體溢位
※ 編輯: x246libra (61.220.35.157), 11/03/2017 17:41:55
35F:→ loveflames: 如果不是有心細究程式在記憶體的架構,就避開這種事 11/03 17:39
36F:→ stupid0319: 有些遊戲機的破解就是利用遊戲存檔名造成溢位 11/03 17:40
37F:→ stupid0319: 用精心設計的檔名字串把程式碼導向別地方 11/03 17:41
38F:→ x246libra: 我是想說 似乎人家都說C語言重視記憶體規劃 11/03 17:42
39F:→ x246libra: 所以才想說多瞭解一點 這程式記憶體溢位是如何產生 11/03 17:43
40F:→ loveflames: 這不是C的層次,而是OS了,如果對PE或ELF有興趣再看 11/03 17:45
41F:→ x246libra: 謝謝您的熱心回答 11/03 17:48