1、函数的定义、声明、分类以及调用
1.1、函数声明:如果函数声明在main()函数之后,需要进行函数声明,反正不需要,并且函数声明可以在函数体外
返回值类型 函数名(类型1 形参1,类型2 形参2);
返回值类型 函数名(类型1,类型2...);
#include
#include
void printLog(int a);
int getNum(int);//声明函数
void main() {
int b= 10;
printLog(b);
printLog(getNum(20));
printf("半径是4,圆的面积是:%0.7lf\n",atan(1.0)*4*4);//库函数求圆面积
}
void printLog(int a) {
printf("打印参数=%d\n",a);
}
int getNum(int b){
return b;
}
1.2、函数分类:
1、来源分类为库函数和用户自定义函数
2、有无返回值分为有返回值函数和无返回值函数。返回值为int类型的,声明的时候可以省略不写。不会报错,但是不美观。在 C 语言中,由于参数传递是按值传递而非按引用传递,函数返回一个数组需要使用指针的方式进行传递或返回。因此,在不使用指针的情况下,函数无法返回一维数组或二维数组类型的值。
3、参数传递角度分为无参函数和有参函数
冒泡排序写法
#include
#include
#define X 12
//#define Y 4
void printLog(int a);
int getNum(int);
void sortArray(int [X]);
void printArray(int [X]);
void main() {
int b= 10;
printLog(b);
printLog(getNum(20));
printf("半径是4,圆的面积是:%0.7lf\n",atan(1.0)*4*4);
int c[X]= {11,20,15,44,34,65,23,72,9,120,88,111};
sortArray(c);
printArray(c);
}
void printLog(int a) {
printf("打印参数=%d\n",a);
}
int getNum(int b){
return b;
}
void sortArray(int m[X]){
int tmp;
for (int i=1;i<=X-1;i++){
for(int j=0;j<X-i;j++){
if (m[j] > m[j+1]) {
tmp = m [j];
m[j] = m[j+1];
m[j+1] = tmp;
}
}
}
}
void printArray(int m[X]){
int tmp;
for (int i=0;i<X;i++){
printf("%d ",m[i]);
}
}
1.3、函数的形参实参分别占据独立的内存单元,参数传递的是值传递,形参的改变不会影响实参。
void swap(int a,int b){
printf("交换前:a=%d,b=%d\n",a,b);
int tmp = 0;
tmp = a;
a = b;
b = tmp;
printf("交换后:a=%d,b=%d\n",a,b);
}
2、数组作为函数参数:(1)数组元素作为函数实参; (2)数组名作为函数实参
1、使用数组元素作为实参,在循环语句控制下将数组元素a[i]的值传递给形参x,并将其值减32后保存数数组元素b[i]中,调用函数时,形参x的值发生了改变,而实参a[i]的值并没有发生变化。
#include
char change(char a);
void main(){
printf("以数组作为函数实参\n");
change('m');
int i=0;
char a[] ="hello",b[10];
for (;a[i]!='\0';i++)
b[i]= change(a[i]);
b[i]='\0';
}
char change(char a){
printf("将小写字母转化为大写字母\n");
printf("转化前小写字母:%c\n",a);
printf("转化后大写字母:%c\n",a-32);
return a-32;
}
2、数组名作为函数的实参
数组名作为函数实参时,形参应当用数组或者指针。由于数组名表示数组的首地址,因此实参向形参传递的不是数组的值,而是实参的首地址,这样的形参数组和实参数组共占用相同的内存单元。
(1)定义函数时,形参数组可以省略数组的长度,直接写成char b[ ]。
(2)实参为数组名,如在change(a);语句中的a就是数组名。调用函数时,会将实参数组a的首地址传递给形参数组b,因此形参和实参的对应元素(如a[0]和b[0],…a[9]和b[9])共占用同一内存单元。
(3)由于形参数组和实参数组共占用相同的内存单元,因此改变形参数组b[ ]的值,实参数组a[ ]的值也会跟着改变。
多维数组名也可以作为函数实参,此时被调用函数中形参数组可以指定每一维的大小,也可省略第一维的大小,但第二维的大小不能省略,而且要和实参数组第二维的大小相同。二维数组是由若干个一维数组组成的,在内存中,数组按行存放,因此在定义二维数组的时候,必须指定列数(第二维),以便系统能够区分每一行。
#include
char change(char a);
void superChange(char b[]);
void main(){
printf("以数组作为函数实参\n");
puts("调用前函数的值:");
change('m');
int i=0;
char a[] ="hello",b[10];
for (;a[i]!='\0';i++)
b[i]= change(a[i]);
b[i]='\0';
puts("调用后函数的值:");
puts(b);
superChange(a);
}
char change(char a){
//printf("将小写字母转化为大写字母\n");
//printf("转化前小写字母:%c\n",a);
//printf("转化后大写字母:%c\n",a-32);
return a-32;
}
void superChange(char b[10]){
int i=0;
for (; b[i]!='\0'; i++){
b[i]=b[i]-32;
}
printf("调用函数的结果:");
puts(b);
}
函数参数传递的方式有两种: 按值传递:参数传递时将实参的值传递给了形参,形参和实参各占独立的内存单元。在这种结合方式下,即使形参的值在函数中发生了变化,也不会影响到实参。 按址传递:参数传递时将实参的地址传递给形参,形参和实参占用相同的内存单元。在这种结合方式下,如果形参的值改变了,实际上实参的值也会改变。