C语言入门系列之8.指针的概念与应用 您所在的位置:网站首页 c语言与指针相关的五个概念是 C语言入门系列之8.指针的概念与应用

C语言入门系列之8.指针的概念与应用

2024-07-09 04:06| 来源: 网络整理| 查看: 265

文章目录 一、指针引入1.地址的概念2.初识指针3.两个操作符 二、指针与指针变量1.定义指针变量*2.指针变量的引用&3.对&和*运算符的说明 三、数组与指针1.指向数组元素的指针2.通过指针引用数组元素3.用数组名作函数参数4.多维数组与指针基本概念指向多维数组元素的指针变量 四、字符串与指针1.字符串定义2.字符串中字符的存取方法3.字符指针作函数参数4.字符指针变量和字符数组的比较 五、指向函数的指针1.用函数指针变量调用函数2.用指向函数的指针作函数参数3.返回指针值的函数指针函数和函数指针的区别 4.指针数组和指向指针的指针5.指针数组作为main函数的形参 六、指针小结1.数据类型小结2.指针运算小结3.void类型和const修饰指针扩展-memcpy

一、指针引入

指针是C语言中的一个重要的概念,也是C语言的一个重要特色。 正确而灵活地运用它,可以有效地表示复杂的数据结构;能动态分配内存;能方便地使用字符串;有效而方便地使用数组等。 掌握指针的应用,可以使程序简洁、紧凑、高效。可以说,不掌握指针就是没有掌握C的精华。

1.地址的概念

数据在内存中的存储和读取如下: 数据在内存中的存储和读取 内存区的每一个字节有一个编号,称为地址。 如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。

在C语言中,对变量的访问有两种方式:

直接访问 如a=5;。 系统在编译时,已经对变量分配了地址,例如,若变量a分配的地址是2000,则该语句的作用就是把常数5保存到地址为2000的单元。间接访问 如scanf("%d",&a);。 调用函数时,把变量a的地址传递给函数scanf,函数首先把该地址保存到一个单元中,然后把从键盘接收的数据通过所存储的地址保存到a变量中。 2.初识指针

在C语言中,指针是一种特殊的变量,它是存放地址的。 假设我们定义了一个指针变量int *i_pointer,通过语句i_pointer = &i;来存放整型变量i的地址,如下: 初始指针-指针的定义和存放 将i的地址(2000)存放到i_pointer中,这时,i_pointer的值就是(2000) ,即变量i所占用单元的起始地址。 要存取变量i的值,可以采用间接方式: 先找到存放i的地址的变量i_pointer,从中取出i的地址(2000),然后取出i的值3,如下: 间接方式取变量值

3.两个操作符

*:是取值操作符; &:是取址操作符。

如:

int i = 2000; int *pointer; pointer = &i; printf("%d\n", *pointer); 二、指针与指针变量

知道了一个变量的地址,就可以通过这个地址来访问这个变量,因此,又把变量的地址称为该变量的指针。 C语言中可以定义一类特殊的变量,这些变量专门用来存放变量的地址,称为指针变量。 指针变量的值(即指针变量中存放的值)是地址(即指针)。

1.定义指针变量*

定义指针变量的一般形式为:

类型说明符 *变量名;

其中,*表示这是一个指针变量,变量名即为定义的指针变量名,类型说明符表示本指针变量所指向的变量的数据类型。 例如float *pointer_1;中,指针变量名是pointer_1,而不是*pointer_1。

下面都是合法的定义:

float *pointer_3; // pointer_3是指向float型变量的指针变量 char *pointer_4; // pointer_4是指向字符型变量的指针变量

可以用赋值语句使一个指针变量得到另一个变量的地址,从而使它指向一个该变量,如下: 定义指针指向变量 在定义指针变量时必须指定基类型。 需要特别注意,只有整型变量的地址才能放到指向整型变量的指针变量中,如下∶

float a; int * pointer_1; pointer_1 = &a;

将float型变量的地址放到指向整型变量的指针变量中,是错误的。

2.指针变量的引用&

指针变量中只能存放地址(指针),不要将一个整数(或任何其他非地址类型的数据)赋给一个指针变量,否则编译器也会把该值当成一个地址来处理。 C语言中提供了地址运算符&来表示变量的地址,其一般形式为:

&变量名;

如&a表示变量a的地址,&b表示变量b的地址。 当然,变量本身必须预先声明。

通过指针变量访问整型变量练习如下:

#include int main(){ int a, b; int *pointer_1, *pointer_2; a = 100; b = 10; pointer_1 = &a; pointer_2 = &b; printf("%d, %d\n", a, b); printf("%d, %d\n", *pointer_1, *pointer_2); return 0; }

打印:

100, 10 100, 10

运行原理如下: 通过指针变量访问整型变量练习

3.对&和*运算符的说明

如果已执行了语句pointer_1 = &a;: (1)&*pointer_1的含义是: &和*两个运算符的优先级别相同,但按自右而左方向结合,因此先进行*pointer_1的运算,它就是变量a,再执行&运算; 因此,&*pointer_1与&a相同,即变量a的地址。 如果有pointer_2 = &*pointer_1;,它的作用是将&*(a的地址)赋给pointer_2 ,如果pointer_2原来指向b,经过重新赋值后它已不再指向b了,而指向了a,如下: 重新赋值改变指向 (2) *&a的含义是: 先进行运算&a,得a的地址,再进行*运算,即&a所指向的变量,也就是变量a; *&a和*pointer_1的作用是一样的,它们都等价于变量a,即*&a与a等价。

(3)(*pointer_1)++相当于a++。 其中,括号是必要的,如果没有括号,就成为了*pointer_1++,而++和*为同一优先级别,而结合方向为自右而左,因此它相当于*(pointer_1++)。 由于++在pointer_1的右侧,是后加,因此先对pointer_1的原值进行*运算,得到a的值,然后使pointer_1的值改变,这样pointer_1不再指向a了。

练习: 输入a和b两个整数,按先大后小的顺序输出a和b。 代码如下:

#include int main(){ int *p1, *p2, *p, a, b; scanf("%d %d", &a, &b); p1 = &a; p2 = &b; if(a void swap(int *p1, int *p2); int *pointer_1, *pointer_2, a, b; scanf("%d %d", &a, &b); pointer_1 = &a; pointer_2 = &b; if(a int temp; printf("Swaping......\nPlease wait^_^\n"); temp = *p1; *p1 = *p2; *p2 = temp; }

打印:

5 9 Swaping...... Please wait^_^ 9 > 5

执行过程如下: 指针变量作为函数参数练习

练习: 输入a、b、c3个整数,按大小顺序输出。 代码如下:

#include int main(){ void exchange(int *p1, int *p2, int *p3); int *p1, *p2, *p3, a, b, c; scanf("%d %d %d", &a, &b, &c); p1 = &a; p2 = &b; p3 = &c; exchange(p1, p2, p3); printf("%d > %d > %d\n", a, b, c); return 0; } void exchange(int *p1, int *p2, int *p3){ void swap(int *q1, int *q2); if(*p1 swap(p1, p3); } if(*p2 int temp; printf("Swaping......\nPlease wait^_^\n"); temp = *q1; *q1 = *q2; *q2 = temp; }

打印:

20 12 25 Swaping...... Please wait^_^ Swaping...... Please wait^_^ 25 > 20 > 12 三、数组与指针

一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。 指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放到一个指针变量中)。 所谓数组元素的指针就是数组元素的地址。

1.指向数组元素的指针

定义一个指向数组元素的指针变量的方法,与以前介绍的指向变量的指针变量相同。 例如,int a[10];定义a为包含10个整型数据的数组; int *p定义p为指向整型变量的指针变量。 应当注意,如果数组为int型,则指针变量的基类型亦应为int型。 对该指针变量赋值:

p = &a[0];

把a[0]元素的地址赋给指针变量p,也就是使p指向a数组的第0个元素,如下图: 对指针变量赋值

2.通过指针引用数组元素

引用一个数组元素,有2种方式:

下标法 如a[i]。指针法 如*(a+i)或*(p+i)。

其中的a是数组名,p是指向数组元素的指针变量,其初值p=a。 数组名即翻译成数组的第一个元素的地址。

练习: 输出数组中的全部元素: 假设有一个a数组,整型,有10个元素,要输出各元素的值有三种方法: (1)下标法。 (2)通过数组名计算数组元素地址,找出元素的值。 (3)用指针变量指向数组元素。

方式一代码如下:

#include int main(){ int a[10], i; for(i = 0; i printf("%d ", a[i]); } return 0; }

打印:

1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10

方式二代码如下:

#include int main(){ int a[10], i; for(i = 0; i printf("%d ", *(a + i)); } return 0; }

运行效果与方式一相同。

方式三代码如下:

#include int main(){ int a[10], i, *p; for(i = 0; i printf("%d ", *p); } return 0; }

运行效果与之前相同。

3.用数组名作函数参数

形式为:

f(int arr[], int n)

在编译时是将arr按指针变量处理的,相当于将函数f的首部写成f(int *arr, int n),这两种写法是等价的。

C语言调用函数时虚实结合的方法都是采用值传递方式,当用变量名作为函数参数时传递的是变量的值,当用数组名作为函数参数时,由于数组名代表的是数组首元素地址,因此传递的值是地址,所以要求形参为指针变量。

练习: 将数组a中n个整数按相反顺序存放,如下: 用数组名作函数参数练习 常规方式代码如下:

#include int main(){ void reverse(int x[], int n); int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2}; printf("The original array:\n"); for(i = 0; i printf("%d ", a[i]); } printf("\n"); return 0; } void reverse(int x[], int n){ int temp, i, j, m; m = (n - 1) / 2; for(i = 0; i void reverse(int *a, int n); int i, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2}; printf("The original array:\n"); for(i = 0; i printf("%d ", a[i]); } printf("\n"); return 0; } void reverse(int *x, int n){ int temp, *i, *j, *p, m; m = (n - 1) / 2; i = x; j = x + n - 1; p = x + m; for( ; i void find_max_min(int a[], int n); int i, a[10]; printf("Input 10 numbers:\n"); for(i = 0; i max = min = a[0]; int i; for(i = 1;i max = a[i]; } else if(a[i] void find_max_min(int *a, int n); int i, a[10]; printf("Input 10 numbers:\n"); for(i = 0; i max = min = *a; int i; for(i = 1;i max = *(a + i); } else if(*(a + i) int a[10]; f(a, 10); } void f(int x[], int n){ ... }

(2)实参用数组名,形参用指针变量,如:

void main(){ int a[10]; f(a, 10); } f(int *a, int n){ ... }

(3)实参形参都用指针变量。例如:

void main(){ int a[10], *p = a; f(p, 10); } void f(int *x, int n){ ... }

(4)实参为指针变量,形参为数组名,如:

void main(){ int a[10], *p = a; f(p, 10); } void f(int x[], int n){ ... }

练习: 对数组中10个整数按由大到小顺序排序。 代码如下:

#include int main(){ void sort(int x[], int n); int i, *p, a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2}; printf("The original array:\n"); for(i = 0; i printf("%4d", *p); p++; } return 0; } void sort(int x[], int n){ int i, j, k, t; for(i = 0;i if(x[j] > x[k]){ t = x[j]; x[j] = x[k]; x[k] = t; } } } }

打印:

The original array: 3 7 9 11 0 6 7 5 4 2 The sorted array: 11 9 7 7 6 5 4 3 2 0 4.多维数组与指针 基本概念

用指针变量可以指向一维数组中的元素,也可以指向多维数组中的元素; 但在概念上和使用上,多维数组的指针比一维数组的指针要复杂一些。

可以认为二维数组是数组的数组,如定义int a[3][4] = {{1, 3, 5, 7}, {9, 11, 13, 15}, {17, 19, 21, 23}};,二维数组a是由3个一维数组所组成的。 设二维数组的首行的首地址为2000,则有: 内存中存放二维数组

在二维数组中,常见表达式及其含义如下: 二维数组表达式及含义 练习: 输出二维数组有关的值。 代码如下:

#include int main(){ int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; printf("a: %d\n", a); printf("*a: %d\n", *a); printf("a[0]: %d\n", a[0]); printf("&a[0]: %d\n", &a[0]); printf("&a[0][0]: %d\n", &a[0][0]); printf("a+1: %d\n", a+1); printf("*(a+1): %d\n", *(a+1)); printf("a[1]: %d\n", a[1]); printf("&a[1]: %d\n", &a[1]); printf("&a[1][0]: %d\n", &a[1][0]); printf("a+2: %d\n", a+2); printf("*(a+2): %d\n", *(a+2)); printf("a[2]: %d\n", a[2]); printf("&a[2]: %d\n", &a[2]); printf("&a[2][0]: %d\n", &a[2][0]); printf("a[1]+1: %d\n", a[1]+1); printf("*(a+1)+1: %d\n", *(a+1)+1); printf("*(a[1]+1): %d\n", *(a[1]+1)); printf("*(*(a+1)+1): %d\n", *(*(a+1)+1)); return 0; }

打印:

a: 6487536 *a: 6487536 a[0]: 6487536 &a[0]: 6487536 &a[0][0]: 6487536 a+1: 6487552 *(a+1): 6487552 a[1]: 6487552 &a[1]: 6487552 &a[1][0]: 6487552 a+2: 6487568 *(a+2): 6487568 a[2]: 6487568 &a[2]: 6487568 &a[2][0]: 6487568 a[1]+1: 6487556 *(a+1)+1: 6487556 *(a[1]+1): 6 *(*(a+1)+1): 6 指向多维数组元素的指针变量

把二维数组a分解为一维数组a[0]、a[1]、a[2]之后,设p为指向二维数组的指针变量,可定义为:

int (*p)[4]

它表示p是一个指针变量,它指向包含4个元素的一维数组。 p指向第一个一维数组a[0],其值等于a、a[0]、&a[0][0]等; p+i则指向一维数组a[i]。

*(p+i)+j是二维数组i行j列的元素的地址,而*(*(p+i)+j)则是i行j列元素的值。 二维数组指针变量说明的一般形式为:

类型说明符 (*指针变量名)[长度]

其中类型说明符为所指数组的数据类型,*表示其后的变量是指针类型,长度表示二维数组分解为多个一维数组时,一维数组的长度,也就是二维数组的列数。

练习: 用指针变量输出二维数组元素的值。 代码如下:

#include int main(){ int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; int (*p)[4]; int i, j; p = a; for(i = 0;i printf("%4d", *(*(p + i) + j)); } printf("\n"); } return 0; }

打印:

1 2 3 4 5 6 7 8 9 10 11 12

练习: 通过输入指定行数和列数打印出二维数组对应任一行任一列元素的值。 代码如下:

#include int main(){ int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; int (*p)[4], i, j; p = a; printf("i = "); scanf("%d", &i); while(i = 3){ printf("i = "); scanf("%d", &i); } printf("j = "); scanf("%d", &j); while(j = 4){ printf("j = "); scanf("%d", &j); } printf("a[%d, %d] = %d\n", i, j, *(*(p+i)+j)); return 0; }

打印:

i = 3 i = 2 j = -1 j = 2 a[2, 2] = 11 四、字符串与指针 1.字符串定义

字符数组形式: 用字符数组存放一个字符串。

练习: 定义一个字符数组,对它初始化,然后输出该字符串。 代码如下:

#include int main(){ char string[] = "I love China!"; printf("%s", string); return 0; }

打印:

I love China!

存放原理如下: 字符数组定义字符串

指针形式: 用字符指针指向一个字符串。

练习: 定义一个字符指针,用字符指针指向字符串中的字符。 代码如下:

#include int main(){ char *string = "I love China!"; printf("%s", string); return 0; }

打印:

I love China! 2.字符串中字符的存取方法

对字符串中字符的存取,可以用下标方法,也可以用指针方法。

练习: 将字符串a复制为字符串b。 下标法:

#include int main(){ char a[] = "I love China!",b[40]; int i; for(i = 0;*(a+i) != '\0';i++){ *(b+i) = *(a+i); } *(b+i) = '\0'; printf("String a is: \n%s\n", a); printf("String b is: \n"); for(i=0;b[i]!='\0';i++){ printf("%c", b[i]); } return 0; }

打印:

String a is: I love China! String b is: I love China!

指针方法:

#include int main(){ char a[] = "I love China!",b[40], *p1, *p2; p1 = a; p2 = b; for( ;*p1 != '\0';p1++, p2++){ *p2 = *p1; } *p2 = '\0'; printf("String a is: \n%s\n", a); printf("String b is: \n"); int i; for(i=0;b[i]!='\0';i++){ printf("%c", b[i]); } return 0; }

执行效果与下标法相同。

3.字符指针作函数参数

练习: 用函数调用实现字符串的复制。 用字符数组做参数代码如下:

#include int main(){ void copy_string(char from[], char to[]); char a[] = "I am a teacher.", b[] = "You are a student."; printf("String a = %s\nString B = %s\n", a, b); printf("Copy string a to string b:\n"); copy_string(a, b); printf("String a = %s\nString B = %s\n", a, b); return 0; } void copy_string(char from[], char to[]){ int i = 0; while(from[i] != '\0'){ to[i] = from[i]; i++; } to[i] = '\0'; }

打印:

String a = I am a teacher. String B = You are a student. Copy string a to string b: String a = I am a teacher. String B = I am a teacher.

形参用字符指针变量代码如下:

#include int main(){ void copy_string(char *from, char *to); char *a = "I am a teacher.", b[] = "You are a student."; printf("String a = %s\nString B = %s\n", a, b); printf("Copy string a to string b:\n"); copy_string(a, b); printf("String a = %s\nString B = %s\n", a, b); return 0; } void copy_string(char *from, char *to){ for( ; *from != '\0'; from++, to++){ *to = *from; } *to = '\0'; }

运行效果与之前相同。 注意: 在定义和初始化b数组时不能通过指针方式,因为指针方式定义的数组为常量,存储在常量区,不可改变,因此调用函数改变b数组时会出现异常。

代码还可以进行简化或改写: 简化1:

#include int main(){ void copy_string(char *from, char *to); char *a = "I am a teacher.", b[] = "You are a student."; printf("String a = %s\nString B = %s\n", a, b); printf("Copy string a to string b:\n"); copy_string(a, b); printf("String a = %s\nString B = %s\n", a, b); return 0; } void copy_string(char *from, char *to){ while((*to = *from) != '\0'){ to++; from++; } }

简化2:

#include int main(){ void copy_string(char *from, char *to); char *a = "I am a teacher.", b[] = "You are a student."; printf("String a = %s\nString B = %s\n", a, b); printf("Copy string a to string b:\n"); copy_string(a, b); printf("String a = %s\nString B = %s\n", a, b); return 0; } void copy_string(char *from, char *to){ while((*to++ = *from++) != '\0'){ ; } }

简化3:

#include int main(){ void copy_string(char *from, char *to); char *a = "I am a teacher.", b[] = "You are a student."; printf("String a = %s\nString B = %s\n", a, b); printf("Copy string a to string b:\n"); copy_string(a, b); printf("String a = %s\nString B = %s\n", a, b); return 0; } void copy_string(char *from, char *to){ while(*from != '\0'){ *to++ = *from++; } *to = '\0'; }

简化4:

#include int main(){ void copy_string(char *from, char *to); char *a = "I am a teacher.", b[] = "You are a student."; printf("String a = %s\nString B = %s\n", a, b); printf("Copy string a to string b:\n"); copy_string(a, b); printf("String a = %s\nString B = %s\n", a, b); return 0; } void copy_string(char *from, char *to){ while(*to++ = *from++){ ; } }

简化5:

#include int main(){ void copy_string(char *from, char *to); char *a = "I am a teacher.", b[] = "You are a student."; printf("String a = %s\nString B = %s\n", a, b); printf("Copy string a to string b:\n"); copy_string(a, b); printf("String a = %s\nString B = %s\n", a, b); return 0; } void copy_string(char *from, char *to){ for( ; *to++ = *from++; ){ ; } }

简化6:

#include int main(){ void copy_string(char *from, char *to); char *a = "I am a teacher.", b[] = "You are a student."; printf("String a = %s\nString B = %s\n", a, b); printf("Copy string a to string b:\n"); copy_string(a, b); printf("String a = %s\nString B = %s\n", a, b); return 0; } void copy_string(char *from, char *to){ char *p1, *p2; p1 = from; p2 = to; while((*p2++ = *p1++) != '\0'){ ; } }

这个方式变得稍复杂了点,重在说明方法。

4.字符指针变量和字符数组的比较

虽然用字符数组和字符指针变量都能实现字符串的存储和运算,但它们二者之间是有区别的,不应混为一谈。 主要概括起来有以下几点: (1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第1个字符的地址),而不是将字符串放到字符指针变量中。 (2)赋值方式: 对字符数组只能对各个元素赋值,不能用以下办法对字符数组赋值。

char str[20]; str = "I love China!";

而对字符指针变量,可以采用下面方法赋值:

char *a; a = "I love China!";

但注意赋给a的不是字符,而是字符串第一个元素的地址。 (3)初始化 对字符指针变量赋初值char *a = "I love China!";等价于

char *a; a = "I love China!";

而对数组的初始化char str[20] = {"I love China!"};不能等价于

char str[20]; str[] = "I love China!";

(4)如果定义了一个字符数组,在编译时为它分配内存单元,它有确定的地址;而定义一个字符指针变量时,给指针变量分配内存单元,在其中可以放一个字符变量的地址。也就是说,该指针变量可以指向一个字符型数据,但如果未对它赋予一个地址值,则它并未具体指向一个确定的字符数据。 例如:

char str[10]; scanf("%s", str);

是可以的,下面的方式:

char *a; scanf("%s", a);

虽然一般也能运行,但这种方法是危险的。 (5)指针变量的值是可以改变的。

改变指针变量的值测试:

#include int main(){ char *a = "I am Corley!!"; printf("%s\n", a); a += 7; printf("%s\n", a); return 0; }

打印:

I am Corley!! rley!!

若定义了一个指针变量,并使它指向一个字符串,就可以用下标形式引用指针变量所指的字符串中的字符。

下标形式引用指针变量测试:

#include int main(){ char *a = "I am Corley!!"; int i; printf("The sixth character is %c\n", a[5]); for(i = 0; a[i] != '\0'; i++){ printf("%c", a[i]); } printf("\n"); return 0; }

打印:

The sixth character is C I am Corley!! 五、指向函数的指针 1.用函数指针变量调用函数

可以用指针变量指向整型变量、字符串、数组,也可以指向一个函数。一个函数在编译时被分配给一个入口地址,这个函数的入口地址就称为函数的指针。

练习: 常规方式代码如下:

#include #if(1) int main(){ int max(int, int); int a, b, c; scanf("%d %d", &a, &b); c = max(a, b); printf("a = %d, b = %d, max = %d\n", a, b, c); return 0; } #endif int max(int a, int b){ return a > b ? a : b; }

打印:

12 20 a = 12, b = 20, max = 20

指针方式:

#include #if(1) int main(){ int max(int, int); int a, b, c; int (*p)(); p = max; scanf("%d %d", &a, &b); c = (*p)(a, b); printf("a = %d, b = %d, max = %d\n", a, b, c); return 0; } #endif int max(int a, int b){ return a > b ? a : b; }

执行效果与常规方式相同。

2.用指向函数的指针作函数参数

函数指针变量常见的用途之一是把指针作为参数传递到其他函数。 函数的参数可以是变量、指向变量的指针变量、数组名、指向数组的指针变量等; 指向函数的指针也可以作为参数,以实现函数地址的传递,这样就能够在被调用的函数中使用实参函数。

//实参函数名 f1   f2 //    ↓ ↓ void sub(int (*x1)(int), int (*x2)(int,int)){ int a, b, i, j; a = (*x1)(i); b = (*x2)(i, j); ... }

其大致原理如下: 有一个函数(假设函数名为sub),它有两个形参(x1和x2),定义x1和x2为指向函数的指针变量。在调用函数sub时,实参为两个函数名f1和f2,给形参传递的是函数f1和f2的地址,这样在函数sub中就可以调用f1和f2函数了。

练习: 设一个函数process,在调用它的时候,每次实现不同的功能(有点类似多态)。 输入a和b两个数,第一次调用process时找出a和b中大者,第二次找出其中小者,第三次求a与b之和。 代码如下:

#include int main(){ int max(int, int); int min(int, int); int sum(int, int); void process(int, int, int(*fun)()); int a, b; printf("Input a and b:\n"); scanf("%d %d", &a, &b); printf("Max = "); process(a, b, max); printf("Min = "); process(a, b, min); printf("Sum = "); process(a, b, sum); return 0; } int max(int a, int b){ return a > b ? a : b; } int min(int a, int b){ return a int result = (*fun)(x, y); printf("%d\n", result); }

打印:

Input a and b: 12 20 Max = 20 Min = 12 Sum = 32 3.返回指针值的函数

一个函数可以返回一个整型值、字符值、实型值等,也可以返回指针型的数据,即地址。 这种带回指针值的函数一般定义形式为:

类型名 *函数名(参数表列);

例如int *a(int x, int y);。

练习: 有若干个学生的成绩(每个学生有4门课程),要求在用户输入学生序号以后,能输出该学生的全部成绩,用指针函数来实现。 代码如下:

#include int main(){ double scores[][4] = {{60.0, 70.0, 80.5, 90.5}, {56.0, 89.0, 67.0, 88.0}, {34.2, 78.5, 90.5, 66.0}}; double *search(double(*pointer)[4], int n); double *p; int i, m; printf("Please input the number of student:"); scanf("%d", &m); printf("The scores of No.%d are:\n", m); p = search(scores, m); for(i = 0; i return *(pointer + n); }

打印:

Please input the number of student:2 The scores of No.2 are: 34.20 78.50 90.50 66.00

改进: 对于前面的练习,找出其中有不及格课程的学生及其学生号。 代码如下:

#include int main(){ double scores[][4] = {{60.0, 70.0, 80.5, 90.5}, {56.0, 89.0, 67.0, 88.0}, {34.2, 78.5, 90.5, 66.0}}; void *search(double(*pointer)[4], int n); search(scores, 3); return 0; } void *search(double(*pointer)[4], int n){ int i, j; for(i = 0; i if(*(p+j) int a[5] = {1, 2, 3, 4, 5}; int *p[5] = {&a[0], &a[1], &a[2], &a[3], &a[4]}; int i; for(i = 0; i void sort(char *name[], int n); void print(char *name[], int n); char *name[] = {"baidu.com", "www.baidu.com", "pan.baidu.com", "baidu.com/profile"}; int n = 4; sort(name, n); print(name, n); return 0; } void sort(char *name[], int n){ char *temp; int i, j, k; for(i = 0; i if(strcmp(name[k], name[j]) > 0){ k = j; } if(k != i){ temp = name[i]; name[i] = name[k]; name[k] = temp; } } } } void print(char *name[], int n){ int i; for(i = 0; i char *name[] = {"baidu.com", "www.baidu.com", "pan.baidu.com", "baidu.com/profile"}; char **p; int i; for(i = 0; i ... }

括号中是空的,实际上,main函数可以有参数,如void main(int argc, char *argv[]),argc和argv就是main函数的形参。 main函数是由操作系统调用的,其形参的值不是在程序中得到,实际上实参是和命令一起给出的,也就是在命令行中包括命令名和需要传给main函数的参数。 命令行的一般形式为:

命令名 参数1 参数2 …… 参数n

练习:

#include #include int main(int argc, char *argv[]){ int i; printf("The number of string is: %d\n", argc - 1); for(i = 1;i printf( "Function:\tmemcpy without overlap\n" ); printf( "Source:\t\t%s\n", string1 + 40 ); printf( "Destination:\t%s\n", string1 + 16 ); memcpy( string1 + 16, string1 + 40, 3 ); printf( "Result:\t\t%s\n", string1 ); printf( "Length:\t\t%d characters\n\n", strlen(string1)); memcpy( string1 + 16, string2 + 40, 3 ); printf( "Function:\tmemmove with overlap\n" ); printf( "Source:\t\t%s\n", string2 + 4 ); printf( "Destination:\t%s\n", string2 + 10 ); memmove( string2 + 10, string2 + 4, 40 ); printf( "Result:\t\t%s\n", string2 ); printf( "Length:\t\t%d characters\n\n", strlen(string2)); printf( "Function:\tmemcpy with overlap\n" ); printf( "Source:\t\t%s\n", string1 + 4 ); printf( "Destination:\t%s\n", string1 + 10 ); memcpy( string1 + 10, string1 + 4, 40 ); printf( "Result:\t\t%s\n", string1 ); printf( "Length:\t\t%d characters\n\n", strlen(string1)); }

打印:

Function: memcpy without overlap Source: fox Destination: dog jumps over the lazy fox Result: The quick brown fox jumps over the lazy fox Length: 43 characters Function: memmove with overlap Source: quick brown fox jumps over the lazy dog Destination: brown fox jumps over the lazy dog Result: The quick quick brown fox jumps over the lazy dog Length: 49 characters Function: memcpy with overlap Source: quick brown dog jumps over the lazy fox Destination: brown dog jumps over the lazy fox Result: The quick quick brown dog jumps over the lazy fox Length: 49 characters


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有