你的具體問題是,你的背後有沒有input
存儲。這是一個未初始化的指針,指向內存中的隨機點,這不太可能有用。
您可以使用類似:
char *input = malloc (100);
// check that input != NULL
// use it
free (input);
或:
char input[100];
但你必須與你使用的scanf
一個嚴重的問題(見下文)。
你應該從未使用scanf
無界%s
(或任何變體,除非你完全控制輸入)。這是一種容易發生緩衝溢出的危險做法,越早戒除就越好。這類似於gets()
。
從我之前的回答中,下面的這段代碼(與您的主代碼結合在一起)提供了一種獲取用戶輸入的安全方法。你傳遞一個可選的提示,緩衝區來加載輸入,以及緩衝區的大小。
它將返回輸入到緩衝區(如果有的剝去新行),然後清除掉,如果必要的,這樣不會影響接下來的輸入操作行的其餘部分的大小。它會在文件結束時返回OK或錯誤指示,或者輸入太長(如果您想對其執行某些操作,您仍會得到輸入的第一部分)。
一旦你的線,你可以sscanf
它,安全,你的心臟的內容。然而,這不是你的要求,因爲你只是想獲得一個字符串。只需使用直接返回的緩衝區即可。
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
int main(void) {
char input[10];
int rc = getLine ("prompt> ", input, sizeof (input));
switch (rc) {
case NO_INPUT: printf ("\nNo input recieved\n"); break;
case TOO_LONG: printf ("Too long, truncated input below:\n");
default: printf("Your input was [%s]\n", input);
}
return 0;
}
把那一個鏡頭,它比它自己使用scanf("%s")
穩健得多。
至於你更新問爲什麼這個工程:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
/* prompt */
char input;
printf("prompt>");
scanf("%s", &input);
printf("%s", &input);
return 0;
}
這是不確定的代碼。期。您只爲字符分配空間,但您使用字符串進行掃描。由於字符串是所有字符後跟零字符的字符數組,因此您可以安全輸入的唯一字符串將是空字符。
其他任何東西都會寫入字符和,無論發生什麼情況與堆棧上的字符相鄰。
這是分配char input[100]
然後輸入200個字符沒有什麼不同,它仍然緩衝區溢出,應予以避免。以下討論基於C的特定實現,不一定全部實現。
有機會,你在這裏很幸運。編譯器可能會生成代碼來保持堆棧指針對齊,即使您要求輸入一個字節,也可以爲四個空間分配空間(甚至更多,這取決於體系結構 - 爲了簡單起見,我假設大多數類型都是四個字節)。另外,你可能會發現你也可以安全地覆蓋argc integer和argv指針的八個字節(即使你不使用它們,它們可能仍然存在,沒有一點指出有兩組不同的啓動指針, up代碼只是爲了保存堆棧中的幾個字節)。
如果您還寫的是,你最終會覆蓋從main
返回地址到你的啓動代碼。 然後你會知道它,因爲當main
退出時,你的代碼將進入la-la land。
未定義行爲,任何事情都有可能發生。有時候的任何東西都包含了它可以完美工作的可能性(類似於「在空中經常扔一副牌,他們最終會落入一個漂亮的整齊排列的堆中」,但是隨機少一點)。
這並不會使未定義的行爲更糟糕。
是的,有時代碼可能有效。它只會覆蓋你的堆棧上的一些東西,導致崩潰或潛在的安全漏洞。 – wj32 2010-09-17 01:45:16