2010-04-10 112 views
1

我實踐的作用在C和遇到的程序....函數原型聲明

#include<stdio.h> 

int main() 
{ 
    float a=15.5; 
    char ch ='C'; 
    printit(a,ch); 
    return 0; 
} 

printit(a,ch) 
{ 
    printf("%f\n%c",a,ch); 
} 

我想知道,爲什麼上面的程序編譯並沒有給出錯誤,因爲我瞭解到目前爲止是...

  1. 在C函數必須與特定原型聲明(但此方案不包含原型)

  2. 爲什麼程序給爲char變量輸出'x'?

  3. c中的函數是否可以接受該值,而不需要像在函數聲明中所做的那樣聲明參數類型?

+6

聞起來像是青少年的家庭作業 – Jack 2010-04-10 17:44:29

+0

@傑克 - 這是名字中的「101」嗎?弗洛伊德滑倒? – 2010-04-10 18:13:08

回答

0
  1. 當你調用從主,主要需求爲printit()瞭解爲printit。解決這個問題的一種方法是在main上面定義printit。
  2. printf應該打印「15.5」,然後是換行符,然後是「C.」。
  3. 我對這個問題感到困惑。 printit()的聲明應該是void printit(float a,char ch);

    void printit(float a, char ch) { 
     printf("%f\n%c",a,ch); 

    } 

    int main() 
    { 
     float a=15.5; 
     char ch ='C'; 
     printit(a,ch); 
     return 0; 
    } 
 
+1

「我對這個問題感到困惑,函數需要定義參數。」不,它們不在C中。C默認爲int規則意味着'printit'固有地採用int。 – 2010-04-10 17:54:01

+0

你是對的。我會解決它。看起來像不好的做法,雖然... – WhirlWind 2010-04-10 17:56:11

0

該代碼應該幾乎可以肯定閱讀:

#include <stdio.h> 

void printit(float a, char ch); 

int main() 
{ 
    float a=15.5; 
    char ch ='C'; 
    printit(a,ch); 
    return 0; 
} 

void printit(float a, char ch) 
{ 
    printf("%f\n%c\n",a,ch); 
} 

如果你想將它寫整潔。但是,要解決上述問題:

1)您應該包括一個原型,是的。但是,由於您只編譯一個單元(.c文件),因此編譯器可以很輕鬆地找出函數的位置,因此您的意思是。我得到這個:

test.c:11: warning: conflicting types for ‘printit’ 
test.c:7: note: previous implicit declaration of ‘printit’ was here 

我強烈建議使用-Wall -Werror -pedantic像這樣的警告轉換爲錯誤並中止編譯,逼着你寫正確的代碼,並因此減少以後的bug編譯。

2)我得到15.5,然後C換成新線。我不確定Z從哪裏來。

3)您不必指定類型 - 但是,如果不這樣做,如果類型不兼容,編譯器將不會從中受益。其中一個常見的例子是將數據傳遞給組裝。這不是嚴格需要,但它可能違反了標準C,絕對不是最佳實踐。

2
  1. 在C,如果你不使用它之前,定義一個函數,編譯器推斷一個隱含的定義
  2. 如果不指定函數參數或者返回值類型,默認爲int
  3. 因爲編譯器使用ch參數作爲整數,所以得到'x'。
0

問題1:printitmain之後定義,解決的辦法是把一個函數原型的頂部。 問題2:聲明函數原型正確,(你沒有寫返回和參數類型) 解決方案:

#include <stdio.h> 

void printit(float a, char ch); 

int main() 
{ 
    float a=15.5; 
    char ch ='C'; 
    printit(a,ch); 
    return 0; 
} 

void printit(float a, char ch) 
{ 
    printf("%f\n%c",a,ch); 
} 
4

首先,有一個在C語言中沒有要求提供的函數原型它被稱爲前。在C99版本的語言中,要求在調用函數之前聲明函數,但仍不需要提供原型。

由於您的編譯器沒有抱怨,您必須使用C89/90編譯器,而不是C99編譯器。

其次,在C89/90,當你調用float類型和char的未申報的功能詭計傳遞參數,你在

printit(a,ch); 

做編譯器將執行默認參數促銷活動,實際上傳遞double類型的值和int。您的功能必須相應地定義爲使代碼工作。您將您的功能定義爲

printit(a, ch) 
{ 
    ... 

該定義意味着兩個參數都有類型int。這違反了上述要求。你的代碼的行爲是未定義的。對代碼進行進一步分析或猜測爲什麼它會按打印方式打印某些東西,這已經不再有意義了。您的代碼的行爲再次未定義。

你(未申報)函數可能看起來正確的定義如下

int printit(double a, int ch) 
{ 
    ... 

或者,它可以以K & [R風格被定義爲

printit(a, ch) 
float a; 
{ 
    ... 

這將可能使你的代碼正常工作。但是,更好的方法是在調用之前爲printit提供原型。您要使用哪種原型 - void printit(double a, int ch)void printit(float a, char ch)或其他 - 您需要決定。

+0

我認爲你的「它不再有任何意義進一步分析代碼...」有點強;從標準的角度來看這是真的,因爲行爲是未定義的,但是如果你正在做一些不可移植的東西,那麼現在可能需要調用約定的低級細節等等(特別是如果它*作業:)) – 2010-04-10 18:37:36

+0

@Mike Dinsdale:是的,但是這需要大量的附加信息,比如使用哪種編譯器,什麼是硬件/操作系統平臺等等。 – AnT 2010-04-10 18:44:12

+0

是的,你是對的。在這種情況下,很容易猜測爲什麼15.5似乎打印正確,但我不知道如何回答OP的問題,即爲什麼他沒有更多的信息就得到'x'作爲字符。 – 2010-04-10 18:50:56