簡體   English   中英

main函數可以訪問它下面的函數但不可變嗎?

[英]main function can access function below it but not variable?

考慮以下代碼:

main()
{
    func();
    i = 8;
}
int i;
func()
{

}

我的主函數如何看到並調用func()但不能使用i,這也是在main下面定義的。

快速回答:不要這樣做。 應在使用前顯式聲明所有函數和變量。 早期版本的C允許您使用隱式聲明,但您不應該利用它。

在C89 / C90中(有時稱為“ANSI C”,但並不嚴格准確),如果調用沒有可見聲明的函數,則會創建一個隱式聲明,假設該函數返回int並且接受(提升的)類型的參數通過電話。 對象沒有這樣的隱式聲明。

根據這個規則是一個壞主意。 如果函數實際返回的類型不是int ,或者它的參數與調用中傳遞的參數不匹配,則行為是未定義的,並且編譯器沒有義務告訴您出錯了。

所有被調用的函數在被調用之前都應該有一個顯式聲明,並且該聲明應該是一個原型 ,指定參數的類型。

1999 ISO C標准刪除了“隱式int ”規則,使得調用沒有可見聲明的函數成為非法(違反約束)。 (不幸的是,聲明不需要是原型,但你總是應該使用原型。)許多編譯器仍允許使用舊規則進行調用。 您應該了解如何讓您的編譯器至少警告這些調用。

這是您的程序的更正版本,在C89 / C90,C99和C11中有效:

void func(void);

int i;

int main(void)
{
    func();
    i = 8;
}

void func(void)
{

}

或者你可以簡單地將func的定義移到main的定義之上(除非你有遞歸調用,否則通常不需要“前向聲明”):

void func(void);

int i;

int main(void)
{
    func();
    i = 8;
}

void func(void)
{

}

在C中,調用未聲明的函數會觸發一些規則來構成返回值和參數的類型。 這是一個糟糕的想法,你應該始終啟用捕獲這個錯誤的編譯器警告。 傳遞或返回浮點值而不是int時,或者傳遞比int更寬的指針時,您將獲得破壞。

更好的是,讓您的編譯器處於C99或更高版本模式,而不是C89。 在C99中刪除了隱式聲明,因此您至少需要一個原型。

沒有前向聲明,沒有使用全局變量的規則。

在K&R C中,函數被隱式聲明返回int並在沒有聲明時使用它們時接受任何參數。

省略返回類型也默認為返回類型為int ,因此定義不會與隱式聲明沖突。

從上到下解析源文件時,編譯器需要在使用之前查看所有標識符的聲明。 沒有顯式返回類型的函數的“隱式int”規則僅在C89 / 90中有效。 它已從C99中的標准中刪除。 因此func()需要在C99及更高版本中使用原型。 如果您在C89 / 90模式下進行編譯,則函數func()沒有錯誤。 GCC在C99模式下為您的代碼生成以下警告(沒有語句i=8 ):

$gcc -Wall -Wextra -std=c99 file.c

warning: implicit declaration of function func
warning: return type defaults to int

即使在C89 / 90中,也不對變量i執行這樣的隱式隱式聲明。 一個例外是函數參數。

例如,

int main(i)
{
    func();
    i = 8;
}

沒錯,因為i默認在C89 / 90中輸入int 但它在C99及更高版本中無效。

為了使您的程序在現代C中有效,它應該是:

void func(); // (1) Prototype for func() 

int main(void)  // (2) return type of main() should be int
{
    func();
    extern int i; // (3) refers to the `i` tentatively defined after main()
    i = 8;
}
int i;
void func()
{

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM