回顾:
字符串在字符串常量区,若两个指针中存的都是helloworld!,那么就没必要在内存中存两份,那么puts的输出结果为yes
Printf中不一定只能传“”,也可以传数组的首元素
指向数组的指针
数组指针:能够指向整个数组。与之前学过的指针不同,他们只能指向数组中的一个元素。
int a[10] = {1,2,3,4,5,6,7,8,9,0};
对于数组a而言,数组的数组名a就是首元素的地址。
&a,那么a是一个指针,a的类型就是一个长度为10的一位整形数组,那么&a就是一个指向长度为10的一维数组的指针。
a的类型:int[10];
所以在编写程序过程中,不能写一个int *p;p = &a;二者的类型不匹配
p是一个int 型的指针,而&a是一个长度为10的一维整形数组的指针
如何定义地址变量p:int(*p)[10];
其中,*是一个类型说明符,说明p是一个指针,剩下的int[10]即为指针的基类型。
()是不可省略的,若省略(int*p[10]),则为指针数组,其含义为:定义了一个叫p的数组,其中装有10个int*,p为数组名。
由前面的内容可知,a<=>&a[0],指向数组的指针。a[0]此时是一个长度为4的一维整形数组,a作为数组名,就是该数组首元素的地址。那么a就是一个地址值,但是在编译器中int *p = a编译会报警。
在二维数组中,(a + i)得到的是第i行的地址,*(a + i)得到的是第i行首元素的值,*(*(a + i)+ j)就是第i行第j列元素的值。
数组指针应用:
二维数组求和:
int sumArray(int (*a)[4],int len)
{
int i,j,sum = 0;
for(i = 0;i < len;++i)
{
for(j = 0;j < 4;++j)
{
sum += *(*(a + i) + j);
}
}
return sum;
}
求二维数组每一行的平均值
void advArray(int (*a)[4],int rows,int * result)
{
int i,j;
for(i = 0;i < rows;++i)
{
int sum = 0;
for(j = 0;j < 4;++j)
{
sum += *(*(a + i) + j);
}
result[i] = sum / 4;
}
}
函数指针
形如int (*pfn)(int,int) 的指针就是函数指针,*pfn就是这个函数指针的名字
函数的函数名即为入口地址
函数指针的作用
运用函数指针也还是为了实现间接访问
在函数的入口地址后面加一个(),就表示调用函数
目的:降低程序的耦合性(利用回调函数)
举个例子:打印能被3整除的数
void printArray(int *a,int len,int (*pfn)(int))
{
int i;
for(i = 0;i < len;++i)
{
if(pfn(a[i]) != 0)
{
printf("%d\n",*(a + i));
}
}
}
int div2(int n)
{
return n % 2 == 0;
}
int div3(int n)
{
return n % 3 == 0;
}
int main(void)
{
int a[] = {1,2,3,4,5,6,7,8,9,10,11,12};
int len = sizeof(a) / sizeof(a[0]);
printArray(a,len,div3);
return 0;
}
指针的指针
注意:要实现在被调函数中修改主调函数的值,要传递给被调函数的一定是主调函数的地址
图中,q即为指向指针的指针
当一个指针数组作为实参传递时,形参的类型是指针的指针
练习:
利用二分法查找字符串中的值
void swap(char *a,char *b)
{
char *t;
t = *a;
*a = *b;
*b = t;
}
void reverse(char **s,int len)
{
int i;
for(i = 0;i < len / 2;++i)
{
swap(s+i,s+len + i - 1);
}
}
void sortString(char **s,int len)
{
int i,j;
for(i = 0;i < len - 1;++i)
{
for(j = i + 1;j < len;++j)
{
if(strcmp(s[i],s[j]) > 0)
{
swap(&s[i],&s[j]);
}
}
}
}
char *binaryFind(char **s,int len,char *ss)
{
int begin = 0;
int end = len - 1;
while(begin <= end)
{
int mid = (begin + end) / 2;
if(strcmp(ss,s[mid]) > 0)
{
begin = mid + 1;
}
else if(strcmp(ss,s[mid]) < 0)
{
end = mid - 1;
}
else
{
return s[mid];
}
}
return NULL;
}
int main(void)
{
char *s[] = {"hello","world","china"};
char *ss = "hello";
int len = sizeof(s) / sizeof(s[0]);
sortString(s,len);
int *ret = binaryFind(s,len,ss);
printf("%p\n",ret);
}