C语言-函数
函数基本用法
- 举例:两数求和
#include <stdio.h> int sum(int, int);// 函数的声明,函数的原型 int main(int argc, char const *argv[]) { int m = 10; int n = 20; int s; s = sum(m,n); printf("%d\n", s); } int sum(int a, int b){ int sum; sum = a + b; return sum; }
函数的参数/传递
- 全局变量:即函数体外说明的变量,它们在程序中的每个函数里都是可见的。(不建议使用)
- 复制传递方式:调用函数将实参传递给被调用函数,被调用函数将创建同类型的形参并用实参初始化。形参是新开辟的存储空间,因此,在函数中改变形参的值,不会影响到实参。
#include <stdio.h> void print_pointer(int, double); int main(int argc, char const *argv[]) { int a = 10; double b = 20; printf("%p,%p\n",&a,&b); print_pointer(a,b); printf("%p,%p\n",&a,&b); } void print_pointer(int x, double y){ printf("%p,%p\n",&x,&y); }
- 地址传递方式:按地址传递,实参为变量的地址,而形参为同类型的指针。被调用函数中对形参的操作,将直接改变实参的值(被调用函数对指针的目标操作,相当于对实参本身的操作)。
#include <stdio.h> void swap(int *, int *); int main(int argc, char const *argv[]) { int a = 10; int b = 20; printf("%d,%d\n",a,b); swap(&a,&b); printf("%d,%d\n",a,b); } void swap(int * x, int * y){ int t; t = *x; *x = *y; *y = t; }
函数的传参-数组
- 复制传递方式:实参为数组的指针,形参为数组名(本质是一个指针变量)
// 数组求和 #include <stdio.h> int arry_sum(int data[], int); int main(int argc, char const *argv[]) { int a[] = {2,6,3,9,4}; int sum; int n; printf("%p\n", a); // 0xbfbbae8c n = sizeof(a) / sizeof(int); sum = arry_sum(a, n); printf("%d\n", sum); } int arry_sum(int data[], int n){ // 形参为数组名(本质是一个指针变量)。本质:int * data = a; printf("%p\n", data); // 0xbfbbae8c int sum = 0; int i; for (i = 0; i < n; ++i){ sum += data[i]; } return sum; }
- 地址传递方式:实参为数组的指针,形参为同类型的指针变量
// 编写一个删除字符串中空格的函数 void del_space(char *p); int main(int argc, char *argv[]) { char a[] = " abd dd "; puts(a); del_space(a); puts(a); return 0; } void del_space(char *p){ char *q; q = p; while(*p){ if(*p==' '){ p++; }else{ *q = *p; p++; q++; } *q= '\0'; } }
指针函数
概念:函数的返回值为地址量的函数
-
局部变量运行在栈内存中,函数运行结束就回收内存
-
野指针概念:指针变量中的值是非法的内存地址
-
举例说明及错误演示
char * getstring(); int main(int argc, char *argv[]) { char * r; r = getstring(); printf("%p\n",r); printf("---%s---\n", getstring()); puts(r); return 0; } char * getstring() { // char str[20];// 错误写法(野指针),局部变量运行在栈内存中。函数结束就内存就回收了。 // char str[20] = "welcome"; // 局部变量运行在栈内存中。函数结束就内存就回收了。 // char * str = "welcome"; // 字符串常量,不能修改。 static char str[20]; // 正确 strcpy(str, "hello"); printf("%p\n",str); return str; } // 运行结果 // 0xbfab5fc8 // 0xbfab5fc8 // 0xbfab5fc8 // ---`����V���l�ԅ�_��---
// 将输入的int类型的数字转换为字符串输出 char * itoa(char *p, int n); int main(int argc, char *argv[]) { int n; char s[50], * r; printf("input:"); scanf("%d", &n); itoa(s, n); puts(s); return 0; } char * itoa(char *p, int n){ int r, i = 0, j; // 获取每一位的数字 while (n) { r = n % 10; n /= 10; p[i] = r + '0'; i++; } p[i] = '\0'; // 调整顺序 j = i-1; i = 0; while (i < j) { r = p[i]; p[i] = p[j]; p[j] = r; i++; j--; } return p;// 数组名就是地址 }
函数指针
- 概念:函数指针用来存放函数的地址,这个地址是一个函数的入口地址
#include <stdio.h> int add(int, int); int sub(int, int); int main(int argc, char const *argv[]) { int m = 10, n = 20; int x; // <函数返回的数据类型> (*<函数指针名称>)(<参数说明列表>); int (*p)(int, int); // 函数指针变量说明的形式 // p = add; // x = add(m, n); p = sub; x = (*p)(m, n); printf("%d\n", x); return 0; } int add(int a, int b){ return a + b; } int sub(int a, int b){ return a - b; }