2010-04-10 85 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