指针 数组 函数
关于函数、指针、数组在学习的过程中关于指针 指针函数 函数指针 数组指针 指针数组很容易搞混,所以在这里详细的比较一下:
关于指针:关于复杂类型的指针,理解的时候主要是根据运算符的优先级从变量名开始来一步一步分解的
简单的类型就不举例了这个地方主要解释一下指针数组和数组指针
Int *p[3]:(指针数组 相当于 数组元素都是指针)
1.首先从变量名p开始和[3]结合(“[ ]”优先级比*高),说明是一个数组;
2.再和*结合说明数组元素是指针类型的;
3.最后和int结合 说明指针指向的内容是int类型的;
所以 p是一个由指向int类型数据的指针所组成的数组
Int (*p)[3]:(数组指针 相当于 指向数组的指针)
1.首先从变量名开始由于()的 优先级较高 所以p和*结合是一个指针
2.之后再和”[]”结合 说明指针指向的是一个数组
3.最后和int结合说明数组中的数据都是int类型的
所以p是一个指向有int类型的数据组成的数组的指针
Int **p(这个地方主要是和函数的值传递有关)
指向指针的指针 int类型的说明一级指针所指向的元素是int类型的
指针的指针即是指针的地址
在利用指针参数去申请内存的时候 可以看到它和一般指针参数的区别
还有就是指向指针的指针可以用于访问二位数组
在自己尝试这使用二级指针的时候所犯的错误:
#include<stdio.h>
int main()
{
int arr[2][2] = {{1, 2},{3, 4}};
int **ptr = NULL;
ptr = arr;
printf("arr[0][0] = %4d\n", ptr[0][0]);
printf("arr[0][1] = %4d\n", ptr[0][1]);
}
调试的时候总是段错误(分析的时候:arr所代表的就是二维数组的首地址 也就是说*ptr对应的就是arr[0][0]的值 所以再使用ptr[][]去访问的时候 会出现段错误 ptr就是一个地址 所以这个地方访问的时候 使用一维指针就可以了 没有必要使用二维指针)
#include<stdio.h>
int main()
{
int arr[2][2] = {{1, 2},{3, 4}};
int *ptr = NULL;
ptr = arr;//得到数组的首地址 之后 通过计算位置信息 得到最后的值
printf("arr[0][0] = %4d\n", *ptr);
printf("arr[0][1] = %4d\n", *(ptr + 1));
}
还可以利用数组指针进行访问
#include<stdio.h>
int main()
{
int arr[2][2] = {{1, 2},{3, 4}};
int (*ptr)[2] = NULL;
ptr = arr;//得到数组的首地址 之后 通过计算位置信息 得到最后的值
printf("arr[0][0] = %4d\n", ptr[0][1]);
printf("arr[0][1] = %4d\n", ptr[1][1]);
}
二维指针访问借助于指针数组
#include<stdio.h>
int main()
{
int arr[2][2] = {{1, 2},{3, 4}};
int *ptr[2] = {arr[0], arr[1]};//相当于将二维数组的第一行的首地址和第二行的首地址分别存储在数组中的两个指针内
int **pptr = NULL;
pptr = ptr;//这个时候的pptr就和arr等价了
printf("arr[0][0] = %4d\n", pptr[0][0]);
printf("arr[0][1] = %4d\n", pptr[0][1]);
printf("arr[1][1] = %4d\n", pptr[1][1]);
}
(小结:指针数组和数组指针
int *ptr[5] 相当于分配了一个空间为5的数组 每个元素都是一个指针类型的 指针指向的是int类型的值
int ( *ptr)[5] 相当于定义了未知个数的指针 每个指针指向的都是一个一维个数为5的数组 内容是int类型的数据
(#include<stdio.h>
#include<stdlib.h>
int main()
{
int arr[3][2] = {{1, 2},{3, 4}, {5, 6}};
int (*Ptr)[2] = NULL;
Ptr = arr;
printf("%4d\n", Ptr[0][1]);
printf("%4d\n", Ptr[1][1]);
printf("%4d\n", Ptr[2][0]);
printf("%4d\n", Ptr[2][1]);
}这个地方就是 只声明了长度是2的一维数组 ))
Int(*p)(int) 函数指针
1.p先和 * 结合 说明是一个指针
2.之后和(int)结合 说明是一个函数 即指针指向一个函数 函数参数是int类型的
3.最后再和最外面的int结合 说明函数返回的是一个int类型值
所以 p是一个指向有一个int型参数并且返回类型是int的函数的指针
指向函数的指针包含了函数的地址,可以通过它来调用函数(可以通过将函数的地址赋给这个指针)
Int (*fptr)(int);定义函数指针
Int function();
Fptr = &function;或者直接是fptr = function;(通常单独的一个函数标示符表示的就是它的地址)
调用的时候:
Int data;
data = (*fptr)();或者是data = fptr();实例如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *(*GetMemory)(int num);
char *func(int num)
{
char *ptr = (char *)malloc(sizeof(char) * num);
return ptr;
}
int main()
{
GetMemory = func;
char *str = NULL;
str = (*GetMemory)(20);
strcpy(str,"HelloWrold!\n");
printf("%s", str);
return 0;
}
指针函数 int *ptr(int )
返回值是一个地址 地址指向的是一个在堆区动态分配的内存区域
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *GetMemory(int num)
{
char *ptr = (char *)malloc(sizeof(char) * num);
return ptr;
}
int main()
{
char *str = NULL;
str = GetMemory(20);
strcpy(str,"HelloWrold!\n");
printf("%s", str);
return 0;
}
(小结:指针函数和函数指针最主要的区别就是指针函数 本身就是一个函数 只是函数的返回值是一个指针 函数指针指的是一个指针 这个指针指向的不是一块内存 而指向的是一个函数 内部的值是这个函数的首地址)
下面将分析一个复杂的指针类型:
关于指针 我们需要分清楚:指针的类型 指针所指向的类型 指针本身所占据的内存区和指针指向的内存区(就是指针的值)
指针的类型:只要把指针声明语句中的指针的名字拿掉 剩余的部分就是指针的类型
指针指向的数据类型:同上 只要将指针声明语句中的指针名称和之前的”*”拿掉 剩余的部分就是指针所指向的类型
(指针的类型和指针所指向的类型是两个概念 尤其是在指针的算术运算中显得尤为重要)
指针的值:是指针本身存储的值,是一个内存地址的值,指针所指向的内存区域的起始地址就是这个值,我们所说的指针指向某块内存区域 就是值指针的值是这块内存区域的首地址
指针本身所占据的内存区:可以使用sizeof(指针的类型 进行判断)32位平台中指针本身占据了4个字节
sizeof(char *)长度是4
指针的算数运算:
指针可以加上或减去一个整数,指针的运算和普通的运算最大的区别就是 指针的元算是以单元为单位的
char a[20]
int *ptr = (int *)a;//强制类型转换并不改变a类型
ptr++; 这个地方的自加运算 地址的改变是 ptr + 4(sizeof(int))
总的来说就是ptr + n就是相当于以ptr为基址之后以n * sizeof()为偏移地址进行寻址
指针不能进行相加运算 但是可以进行相减运算 (操作时候必须数据类型相同)
(未完待续......)