传值调用与传址调用
指针是变量,因此可以声明指针参数 ,因此可以声明指针参数
当一个函数体内部需要改变实参的值,则需要使用指针参数 ,则需要使用指针参数
函数调用时实参值将复制到形参
指针适用于复杂数据类型作为参数的函数中
数组地址与数组名
数组名代表数组首元素的地址
数组的地址需要用取地址符&才能得到
数组首元素的地址值与数组的地址值相同
数组首元素的地址与数组的地址是两个不同的概念
数组名可以看做一个常量指针
数组名“指向”的是内存中数组首元素的起始位置
在表达式中数组名只能作为右值使用
只有在下列场合中数组名不能看做常量指针
数组名作为sizeof操作符的参数 数组名作为&运算符的参数
a为数组是数组首元素的地址
&a为整个数组的地址
a和&a的意义不同其区别在于指针运算
C语言中,数组作为函数参数时 ,数组作为函数参数时,编译器将 其编译成对应的指针
void f(int a[])<=>void f(int* a); void f(int a[5])<=>void f(int* a);
一般情况下,当定义的函数中有数组参数时 ,当定义的函数中有数组参数时,需要定 义另一个参数来标示数组的大小
C语言中通过typedef为数组类型重命名 typedef type(name)[size];
数组类型: typedef int(AINT5)[5]; typedef float(AFLOAT10)[10];
数组定义: AINT5 iArray; AFLOAT10 fArray
数组指针
数组指针用于指向一个数组
数组名是数组首元素的起始地址,但并不是数组的起始地址
通过将取地址符&作用于数组名可以得到数组的起始地址
可通过数组类型定义数组指针: ArrayType* pointer;
也可以直接定义:type (*pointer)[n]; pointer为数组指针变量名 type为指向的数组的类型 n为指向的数组的大小
#include <stdio.h>
typedef float(AFLOAT10)[10];
int main()
{
float fArray[10];
AFLOAT10* pf = &fArray;
int i = 0;
for(i=0; i<10; i++)
{
(*pf)[i] = i;
}
指针数组
指针数组是一个普通的数组
指针数组中每个元素为一个指针
数组指针的定义:type* pArray[n]; type*为数组中每个元素的类型 pArray为数组名 n为数组大小 float
#include <stdio.h>
#include <string.h>
int lookup_keyword(const char* key, const char* table[], const int size)
{
int ret = -1;
int i = 0;
for(i=0; i<size; i++)
{
if( strcmp(key, table[i]) == 0 )
{
ret = i;
break;
}
}
return ret;
}
#define DIM(a) (sizeof(a)/sizeof(*a))
int main()
{
const char* keyword[] = {
"do",
"for",
"if",
"register",
"return",
"switch",
"while",
"case",
"static"
};
printf("%d\n", lookup_keyword("return", keyword, DIM(keyword)));
printf("%d\n", lookup_keyword("main", keyword, DIM(keyword)));
}
数组指针本质上是一个指针
数组指针指向的值是数组的地址
指针数组本质上是一个数组
指针数组中每个元素的类型是指针
一维数组名代表数组首元素的地址 int a[5] a的类型为int*
二维数组名同样代表数组首元素的地址 int m[2][5] m的类型为int(*)[5]
void f(int a[5])<=>void f(int a[])<=>void f(int* a);
void g(int a[3][3])<=> void g(int a[][3])<=>void g(int (*a)[3]);
指针数组:int* a[5] 指针的指针:int** a
结论:
1. 二维数组名可以看做是指向数组的常量指针
2. 二维数组可以看做是一维数组
3. 二维数组中的每个元素都是同类型的一维数组
函数的类型由返回值,参数类型和参数个数共同决定 例:
int add(int i, int j)的类型为int(int, int)
C语言中通过typedef为函数类型重命名 typedef type name(parameter list)
例: typedef int f(int, int); typedef void p(int);
函数指针
函数指针用于指向一个函数
函数名是执行函数体的入口地址
可通过函数类型定义函数指针: FuncType* pointer;
也可以直接定义:type (*pointer)(parameter list);
pointer为函数指针变量名 type为指向函数的返回值类型 parameter list为指向函数的参数类型列表
回调函数
#include <stdio.h>
typedef int(*FUNCTION)(int);
int g(int n, FUNCTION f)
{
int i = 0;
int ret = 0;
for(i=1; i<=n; i++)
{
ret += i*f(i);
}
return ret;
}
int f1(int x)
{
return x + 1;
}
int f2(int x)
{
return 2*x - 1;
}
int f3(int x)
{
return -x;
}
int main()
{
printf("x * f1(x): %d\n", g(3, f1));
printf("x * f2(x): %d\n", g(3, f2));
printf("x * f3(x): %d\n", g(3, f3));
}
回调函数带参数
int add(int a,int b);
int sub(int a,int b);
void functionchoose(int a, int b, int (*pf)(int, int));
int main()
{
int a1=3,a2=4;
functionchoose(a1,a2,add);
functionchoose(a1,a2,sub);
return 0;
}
int add(int a, int b)
{
printf("add function \n");
return a+b;
}
int sub(int a, int b)
{
printf("sub function \n");
return a-b;
}
void functionchoose(int a,int b,int (*pf)(int,int))
{
printf("the result is %d \n",(*pf)( a, b));
}