目录
二级指针
我们之前所见到的大部分为一级指针,如:
int * p;
char *p;
float *p;
double *p;
下面我们来了解一下,二级指针;
int main()
{
int a = 10;
int* p = &a;//取出a的地址
//p是指针变量,是一级指针
int* * pp=&p;//pp是二级指针
int** * ppp = &pp;//ppp是三级指针
}
指针数组
指针数组到底是数组还是指针?
类比一下:
整型数组------存放整型的数组(数组中每个元素是整型类型);
int p[10];
字符数组------存放字符的数组(数组中每个元素是字符类型);
char p[10];
指针数组------存放指针的数组(数组中每个元素是指针类型);
int *p[10];
所以,指针数组是一个数组;
指针数组模拟二维数组
模拟出二维数组的效果,并不是二维数组!
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 2,3,4,5,6 };
int arr3[] = { 3,4,5 ,6,7};int* arr[] = { arr1,arr2,arr3 };//指针模拟二维数组
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);// *(*(arr+i)+j)
}
printf("\n");
}
}
字符指针变量
char c = "w";
char* p = &c;//p就是字符指针那char* p = "abcedf";如何理解?
它并不是把abcedf\0,存放在p中,而是把第一个字符的地址存放在p中;
int main()
{char* p = "abcedf";
printf("%c\n", *(p + 2));
printf("%c\n", *(p+1));
//1、可以把字符串想象成一个字符数组,但是这个数组不能修改
printf("%c\n", "abcedf"[3]);
printf("%c\n", p[3]);
//2、当常量字符串出现在表达式中的时候,他的值是第一个字符的地址}
深入理解:
int main()
{
char str1[] = "hello bit." ;
char str2[] = "hello bit." ;const char* str3 = "hello bit." ;
const char* str4= "hello bit." ;
if (str1 == str2)
printf("str1 and str2 are same.\n");
else
printf("str1 and str2 are not same.\n");if (str3 == str4)
printf("str3 and str4 are same.\n");
else
printf("str3 and str4 are not same.\n");
}
代码的打印结果是什么?
为什么会是这个结果?我们来调试一下。
str1和str2并未建立联系,二者是在不同的内存块中存放相同的值,是一个独立的个体;
而str3和str4的指向地址相同;
数组指针变量
什么是数组指针变量?
还是和指针数组一样来类比一下:
整型指针(int *):指向整型的指针--->整型指针变量存放的是整型的地址;
字符指针(char *):指向字符的指针--->字符指针变量存放的是字符的地址;
数组指针:指向数组的指针--->数组指针变量存放的是数组的地址;
所以,数组指针是一个指针;
下面代码哪一个是数组指针变量?
首先我们要知道 [] 的优先级高于 * ;
1、int *p1[10];
2、int *(p2)[10];
1、p1是数组,数组10个元素,每个元素是int *类型;
2、p2是指针,指针指向的是数组,数组有10个元素,每个元素是int类型;
所以p2是数组指针;
int main()
{
int n = 100;
int* pn = &n;char c = 'w';
char* pc = &c;float f = 3.14f;
float* pf = &f;int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
int (*parr) [10] = &arr;//取出数组的地址
//parr就是数组指针}
数组传参
1、一维数组传参
形参可以是数组,也可以是指针;
1、可以写出数组,更加直观;
2、可以写出指针,数组传参传递的是首元素的地址
一维数组传参本质上是传递首元素的地址;
int arr[10];
test(arr,10);
1、void test (int arr[],int sz) {}
2、void test (int *arr,int sz) {}
2、二维数组传参
形参可以写出数组,同样也可以写出指针的形式;
#include<stdio.h>
void Print1(int arr[3][5], int r, int c)
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
void Print2(int (*arr)[5], int r, int c)
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
printf("%d ", *((*(arr+i))+j));
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
//Print1(arr, 3, 5);
Print2(arr, 3, 5);
}
二维数组的首元素的地址如何理解?
函数指针变量
我们知道:
数组名:数组首元素的地址
&数组名:整个数组的地址
函数名:函数的地址
&函数名:函数的地址
int Add(int x, int y)
{
return x + y;
}
int main()
{
//int a = 10;
//int* pa = &a;//整型指针//int arr[10] = { 0 };
//int (*parr)[10]= & arr;//数组指针//函数指针变量,用来存放函数的地址
//printf("%p\n", &Add);
//printf("%p\n", Add);int (*pf)(int,int) = &Add;//pf就是函数指针变量
int ret = Add(3, 5);
printf("%d\n", ret);int ret2 = (*pf)(2, 2);
printf("%d\n", ret2);int ret3 = pf(5, 2);
printf("%d\n", ret3);
}
举例:
理解下面两个代码:
int main()
{
(*(void (*)())0)();
return 0;
}我们进行拆分一下:
先看:void(*)() :这是一个函数指针类型;
对于(int)3.14:这是强制类型转换;
那对于:(void(*)()) 0:也是如此,把0这个整数值强制类型转换成一个函数的地址;
(*(void(*)()) 0)():最后一层也是一个函数指针类型,返回值为void类型;
void (*singal(int, void(*)(int)))(int);
int main()
{
return 0;
}和上面一样进行拆分:
signal是一个函数
signal函数的参数有2个,第一个是int类型
第二个是函数指针类型,该指针指向的函数参数是int,返回类型是void
signal函数的返回类型是这种类型的void(*)(int)函数指针
该指针指向的函数参数是int,返回类型是void
以上就是全部内容,希望有所帮助!