c语言编程函数坐标式,C语言编程之简单函数

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

现在我们可以完全理解printf语句了:原来printf也是一个函数,上例中的printf("sin(pi/2)=%f\nln1=%f

\n", sin(pi/2),

log(1.0))是带三个参数的函数调用,而函数调用也是一种表达式,因此printf语句也是表达式语句的一种,我们调用printf不是为了得到它

的返回值,而是为了利用它所产生的副作用(Side Effect)--打印。C语言的函数可以有Side

Effect,这一点是它和数学函数在概念上的根本区别。

程序第一行的#号(Pound Sign,Number Sign或Hash Sign)和include表示包含一个头文件(Header

File),后面尖括号(Angel

Bracket)中就是文件名(这些头文件通常位于/usr/include目录下)。头文件中声明了我们程序中使用的库函数,根据先声明后使用的原则,

要使用printf函数必须包含stdio.h,要使用数学函数必须包含math.h,如果什么库函数都不使用就不必包含任何头文件,例如写一个程序

int main(void){int a;a=2;return

0;},不需要包含头文件就可以编译通过,当然这个程序什么也做不了。使用math.h中声明的库函数还有一点特殊之处,gcc命令行必须加-lm选项,

因为数学函数位于libm.so库文件中(这些库文件通常位于/lib目录下),-lm选项告诉编译器,我们程序中用到的数学函数要到这个库文件里找。

自定义函数

main()主函数就是一个典型例子。

我们对照着main函数的定义来看语法规则:

#include

int main(void)

{

关于main函数需要注意两点:

(1)书上的main函数定义写成main(){...}的形式,不写返回值类型也不写参数列表,这是Old Style

C的风格

(2)其实操作系统在调用main函数时是传参数的,main函数最标准的形式应该是int main(int argc, char

*argv[])

较简单的自定义函数

a4c26d1e5885305701be709a3d33442f.png

#include

void newline(void)

{

printf("\n");

}

void threeline(void)

{

newline();

newline();

newline();

}

int main(void)

{

printf("Three lines:\n");

threeline();

printf("Another three lines.\n");

threeline();

return 0;

}

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

通过这个简单的例子可以体会到:

1.同一个函数可以被多次调用。

2.可以用一个函数调用另一个函数,后者再去调第三个函数。

3.通过自定义函数可以给一组复杂的操作起一个简单的名字,例如threeline。对于main函数来说,只需要通过threeline这个简单的名字来调用就行了,不必知道打印三个空行具体怎么做,所有的复杂操作都被隐藏在threeline这个名字后面。

4.使用自定义函数可以使代码更简洁,main函数在任何地方想打印三个空行只需调用一个简单的threeline(),而不必每次都写三个printf("\n")。

执行编译时,先从主函数执行,

第一步:执行printf()函数,将字符串字面值输出,然后换行。

第二步:执行

threeline()定义的函数,然后找到对应threeline()函数,执行第一个newline()函数,然后找到newline()函数,执行

printf()函数输出换行。执行完以后返回threeline()函数,再执行第二个newline()函数。执行第三条语句原理是一样的。最后返回

main()主函数,执行输出printf("Another three

lines.\n");语句。调用第二次threeline()函数原理是一样的。执行完以后将0返回。

#include

void newline(void);

void threeline(void);

int main(void)

{

printf("Three lines:\n");

threeline();

printf("Another three lines.\n");

threeline();

return 0;

}

void newline(void)

{

printf("?\n");

}

void threeline(void)

{

newline();

newline();

newline();

}

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

如果注释掉声明void newline(void);和void

threeline(void);,但仍然能编译通过,运行结果也对。这里涉及到的规则称为函数的隐式声明(Implicit

Declaration),在main函数中调用threeline时并没有声明它,编译器认为此处隐式声明了int

threeline(void);,隐式声明的函数返回值类型都是int,由于我们调用这个函数时没有传任何参数,所以编译器认为这个隐式声明的参数类型

是void,这样函数的参数和返回值类型都确定下来了,编译器根据这些信息为函数调用生成相应的指令。然后编译器接着往下看,看到threeline函数

的原型是void

threeline(void),和先前的隐式声明的返回值类型不符,所以报警告。好在我们也没用到这个函数的返回值,所以执行结果仍然正确

形参和实参

我们需要在函数定义中指明参数的个数和每个参数的类型,定义参数就像定义变量一样,需要为每个参数指明类型,参数的命名也要遵循标识符命名规则

#include

void max(int x,int y)

{

if(x>y)

{

printf("%d\n",x);

} else

{

printf("%d\n",y); }

}

int main(void)

{

max(3,4);

return 0;

}

需要注意的是,定义变量时可以把相同类型的变量列在一起,而定义参数却不可以,例如下面这样的定义是错的:

void max(int x, y)

{

if(x>y)

{

printf("%d\n",x);

} else

{

printf("%d\n",y); }

}

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

记住这条基本原理:形参相当于函数中定义的变量,调用函数传递参数的过程相当于定义形参变量并且用实参的值来初始化。

#include

void max(int x,int y)

{

if(x>y)

{

printf("%d\n",x);

} else

{

printf("%d\n",y); }

}

int main(void)

{

int a=3,b=4;

max(a,b);

return 0;

}

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

1、定义一个函数increment,它的作用是把传进来的参数加1。例如:

#include

void increment(int x)

{

x = x + 1;

}

int main(void)

{

int i = 1, j = 2;

increment(i);

increment(j);

printf("%d\n",i);

printf("%d\n",j);

return 0;

}

我们在main函数中调用increment增加变量i和j的值,这样能奏效吗?为什么?

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

#include

void increment(int *x)

{

*x = *x + 1;

}

int main(void)

{

int i = 1, j = 2;

increment(&i);

increment(&j);

printf("%d\n",i);

printf("%d\n",j);

return 0;

}

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

2、如果在一个程序中调用了printf函数却不包含头文件,例如int main(void) { printf("\n");

},编译时会报警告:warning: incompatible implicit declaration of built-in

function ‘printf’。请分析错误原因。

printf是个输出函数,声明头文件"#include

"的作用就是用来提供这些信息的stdio.h是C编译系统提供的一个文件名,stdio是"standard

input &

output"的缩写,即有关标准输入输出的信息。执行main()函数,有个输出函数,找不到系统的标准输入输出函数头文件,因此会报警告。

<4>全局变量、局部变量和作用域

我们把函数中定义的变量称为局部变量(Local

Variable),由于形参相当于函数中定义的变量,所以形参也是一种局部变量。在这里“局部”有两层含义

1、一个函数中定义的变量不能被另一个函数使用。例如max中的x和y在main函数中没有定义,不能使用,同样main函数中的局部变量也不能被max函数使用。如果这样定义:

#include

void max(int x,int y)

{

if(x>y)

{

printf("%d\n",x);

} else

{

printf("%d\n",y); }

}

int main(void)

{

int a=3,b=4,x=5,y=6;

max(a,b);

return 0;

}

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

2、每次调用函数时局部变量都表示不同的存储空间。局部变量在每次函数调用时分配存储空间,在每次函数返回时释放存储空间,例如调用

max(23, 59)时分配x和y两个变量的存储空间,在里面分别存上23和59,函数返回时释放它们的存储空间,下次再调用max(12,

20)时又分配x和y的存储空间,在里面分别存上12和20

全局变量和局部变量

#include

int a =8,b =9;

void aa()

{

printf("%d %d\n",a,b);

}

int main(void)

{

int a= 3;

aa();

printf("%d %d\n",a,b); return 0;

}

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

全局变量任何函数都可以访问,程序运行访问全局变量与书写全局变量顺序有些不同,据有前辈介绍大型项目有些Bug往往是对全局变量读写顺序不正

确而引起的,找Bug困难。因此建议:虽然全局变量用起来很方便,但一定要慎用,能用函数传参代替的就不要用全局变量。在声明主函数前先声明全局变量

a=8,b=9,在main()主函数定义一个a=3局部变量,在main()函数中a的参数为3,其他函数的参数都使用全局变量8,没有声明局部变量的

变量,参数的值都是从全局变量定义中获取。但要注意一点:局部变量可以用类型相符的任意表达式来初始化,而全局变量只能用常量表达式(Constant

Expression)初始化

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值