目录
指针的理解
关于指针,我先讲一个故事:一个侦探在案发现场发现了一张字条,字条上说让他到卧室的床底下寻找第二张字条。侦探找到第二张字条后,字条上说让他到厨房的水槽中找第三张字条。当他找到最后一张字条后。字条上的信息让他破解了这个案件。
这个故事中的字条,就好比指针。
指针是C语言的灵魂,总的来说,有以下三种理解:
1,指针是一种类型,可以定义指针类型的变量。
2,指针就是内存地址,因为其指向了内存空间
3,指针说的是指针变量
指针的关注点
俩种类型:指针本身的类型,指针指向的类型
char *p;int *p;
俩种大小:指针的大小,所能访问的指向空间大小
sizeof(p) sizeof(*p)
字符指针:char *
字符指针是个指针,指向了字符的地址
int main()
{
char str[] = "apple";
char *p = "apple";
printf("%s--%p\n",str,str);
printf("$s--%p\n",p,p);
system("pause");
return 0;
}
上述代码中,str和p的值相同,其地址却不相同,说明指向的并不是同一块空间。
我们再来扩展一下;
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main()
{
char str1[] = "apple";
char str2[] = "apple";
char *p1 = "apple";
char *p2 = "apple";
if (str1 == str2)
{
printf("str1 == str2\n");
}
else
{
printf("str1!=str2\n");
}
if (p1 == p2)
{
printf("p1 == p2\n");
}
else
{
printf("p1!= p2\n");
}
system("pause");
return 0;
}
注意:
字符串给指针进行赋值时,赋值的是字符串的地址
字符数组进行字符串的初始化赋值时,赋值的是字符串内容
无类型指针void *
void 是无类型,通常定义函数的返回值类型或者参数类型表示没有返回值或参数
void 是无类型指针。
通常表示无关大小,只关心指向的指针类型
int * cmp(const void *p1,const void *p2)
{
return *(int*)p1-*(int *)p2;
}
比如上面的代码,参数类型为void *
指针数组
本质是一个数组,数组元素都是指针
char *p[10];
根据算数优先级可得,变量p先和[]结合,为数组,再和*结合,表示数组的每个元素是指针。int表明数组元素是char类型(指针指向char类型).
我们来看一个例子:
定义一个具有20个元素的字符指针数组
char *p[20] = {0};
数组指针
本质是一个指针,指向了一个数组
char (*p)[10];
例子:
定义一个具有10个整型指针元素的数组指针
int* (*p)[10] = NULL;
数组名和&数组名
数组名:数组首元素地址
对数组名取地址:数组的地址(数组指针);
int a[10];
a+1;//第二个元素地址
&a+1;//指向位置跳过整个数组,指向最后一个元素的结尾处
例子:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include<stdlib.h>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *p = (int*)(&a + 1);//强制转换为int*类型,
printf("*(a+1) == %d,*(p-1) == %d",*(a+1),*(p-1));
//*(a+1)为第二个元素地址,接应用后为2,*(p-1)为最后一个元素的地址解引用,即最后一个元素值
system("pause");
return 0;
}
注意:
数字名大多数情况下被认为数组首元素地址,但有俩种情况不同
1,数组名取地址
2,sizeof(数组名)
上述俩中情况数组名代表整个数组,在后面的笔试题中我们会详细介绍。
函数指针
本质是指针,指向了函数的地址.
和数组名一样,函数名可以表示函数的地址。
int (*p)(int a,int b);
例子:
定义一个函数指针变量,指向的函数有int *类型的参数,返回值是char *.
char * (*p)(int *b) = &fun;
回调函数
定义一个函数后,不会直接调用,而是在特定情况下才能调用。
这有个程序员买西瓜的段子,可以方便理解:
女朋友对程序员说ÿ