char *ds = gets();這行代碼在VS2017為什麼可以運行,沒有error?

代碼是我一時手殘打出來的,處理另一個bug時發現,這行代碼應該報錯,但沒有出錯。。

#include&

void f(void)
{
char *ds = gets();
puts(ds);
}

int main(void)
{
//char *ds = gets();
f();

return 0;
}

gcc編譯會提示缺少參數。

VS2017提示的是

警告 C4013 「gets」未定義;假設外部返回 int test 。。。a.c 6

警告 C4047 「初始化」:「char *」與「int」的間接級別不同 test 。。。a.c 6

char *ds = gets();

放在main中會報錯,放在其他函數就不報錯。

可是ds沒有指定地址,也沒有分配內存,為什麼編譯器就放過了它呢?

而且選中函數名,按F12並沒有轉到它的定義,我在VS2017的stdio.h中也沒有找到它的聲明。

感覺有點摸不著頭腦。


因為VS2017的stdio.h裡面沒有了gets,只有gets_s。所以,你如果在VS2017裡面,把gets換做gets_s,你就會獲得gcc一樣的錯誤。而在C語言中,如果一個函數沒有聲明的話,默認就是當作返回int的,所以你會獲得警告gets沒有定義,假設返回int。

而這種函數沒有聲明直接使用的情況在C++是不允許的,所以如果你把.c換做.cpp,調C++編譯器,gets這裡會報錯是未定義的標識符。這是C與C++的一個差別。


vs2017刪掉了gets的聲明(但是定義還在標準庫里,為了兼容)

所以你寫了個gets,C語言會隱式聲明一個int gets(),然後正好和標準庫里的gets鏈接上了,就work了

gets不安全,並且不像scanf可以有使得它變安全的寫法,所以請用fgets


請不要用被移除出標準庫的函數。

gets 從 C11/C++14 起被逐出標準庫。這是目前僅有的被逐出 C 標準庫的函數。

關鍵點藍大已經說了。

個人覺得 VS 這裡處理有點不妥。函數隱式聲明是 C89 的內容,而於 C99 被移除。然而 gets 是 C11 開始移除的。


我想問的是。。。gets不是還要有個buffer做參數嗎?

還有。。C語言竟然可以把int類型直接初始化給指針類型。。嗎?


推薦閱讀:

在寫代碼的時候,加法快還是乘法快還是都一樣?
軟體乘法和硬體乘法哪個效率高?為什麼?
對於學生黨什麼編程語言比較適合?
如何評價"Null reference - my billion-dollar mistake"?

TAG:C編程語言 | VS2017 |