赞
踩
目录
指针就是一个变量,用来存放地址,一个地址唯一标识一块内存空间。
指针大小4/8字节(32位平台/64位平台)
指针是有类型的,其类型决定了指针±整数时的步长,和对其解引用‘*’时的权限(能够操作几个字节)
char arr='d';
char*p=&arr;(取出arr地址放入到p中)
此时*p=='d';
*p='w';(把对应地址存放变量d赋值为w)
其余类型指针情况类似
一个特殊情况
- int main()
- {
- char *str="hello world";
- printf("%s\n",str);
- return 0;
- }
此时打印的结果是hello world,是把hello world放入到str指针变量里了吗?显然不是
"hello world"为常量字符串,本质是把字符串的首地址放入到了str中。
一个练习
- #include <stdio.h>
- int main()
- {
- char s1[] = "hello";
- char s2[] = "hello";
- const char *s3 = "hello";
- const char *s4 = "hello";
- if(s1 ==s2)
- printf("s1等于s2\n");
- else
- printf("s1不等于s2\n");
-
- if(s3 ==s4)
- printf("s3等于s4\n");
- else
- printf("s3不等于s4\n");
-
- return 0;
- }
结果为s1不等于s2
s3等于s4
原因是s3和s4指向的是同一个常量字符串,C/C++会把常量字符串存储单独存储到一个内存区域,当几个指针指向同一个字符串时,实际上会指向同一内存。但是用相同的常量字符串初始化不同数组时就会开辟不同的内存块。
const修饰的常变量(本质还是变量)不能用于arr[中];
const在*同一侧时起的作用都是相同的
const char*p;char const*p,此时*p不能赋值改变
char* const p,此时p不能被赋值改变
用于存放指针的数组
int *arr[5];//存放五个int类型的指针数组
int **arr[5];(二级指针)//存放五个指针指向int*的数组
数组名表示的是数组首元素地址,以下两种情况除外
此时&arr为取出整个数组地址,(但是&arr==arr);sizeof(arr)中的arr为整个数组字节大小
指向数组的指针,用于存放整个数组的地址
int(*p)[5];//p为指针,指向含有五个元素的整型数组。
int*p[5];
[]的优先级高于*,如果不加(),p会和[5]先结合成一个有五个元素的数组
下面举个例子进行练习
- #include <stdio.h>
- int main()
- {
- int arr[10] = { 0 };
- printf("arr = %p\n", arr);
- printf("&arr= %p\n", &arr);
- printf("arr+1 = %p\n", arr+1);
- printf("&arr+1= %p\n", &arr+1);
- return 0;
- }
可以看到arr和&arr的输出是相同的,但是当二者都加1后结果却不相同了,原因就在于,&arr取出的是整个数组地址,加1后跳过的是整个数组
- #include<stdio.h>
- int main()
- {
-
- int arr[5]={1,2,5,4,7};
- int(*p)[5]=&arr;
- return 0;
- }
二维数组传参是传的是第一行元素的地址,行数可以不设置,但列一定要设置
- #include <stdio.h>
- void arr1(int arr[][4], int row, int col)
- {
- int i = 0;
- for(i=0; i<row; i++)
- {
- for(j=0; j<col; j++)
- {
- printf("%d ", arr[i][j]);
- }
-
- printf("\n");
- }
- }
- void arr2(int (*arr)[4], int row, int col) {
- int i = 0;
- for(i=0; i<row; i++)
- {
- for(j=0; j<col; j++)
- {
- printf("%d ", arr[i][j]);
- }
- printf("\n");
- }
- }
- int main()
- {
- int arr[3][4] = {1,2,3,4,5,6,7,8,9,10};
- arr1(arr, 3, 4);
- arr2(arr, 3, 4);
- return 0;
- }
在我们了解以上知识后我们来看看这个int(*arr[8])[6]
对其进行分析arr和[8]相结合,组成一个数组,有8个元素,每个元素为指针类型,指针指向含有6个int型元素的数组,每个元素类型为int(*)[6],存放数组指针的数组。
一维数组传参传的是首元素地址,数组存放是连续的
- #include <stdio.h>
- void test(int arr[])//F or T?
- {}
- void test1(int arr[10])//F or T?[]中的数字没有意义,仅仅是为了方便初学者学习理解,并不会创建一个形参数组
- {}
- void test2(int *arr)//F or T?
- {}
- void test3(int *arr[20])//F or T?
- {}
- void test4(int **arr)//F or T?
- {}
- int main()
- {
- int arr[10] = {0};
- int *arr2[20]={0};//传地址二级指针(地址的地址),每个元素为int*类型
- test(arr);
- test1(arr);
- test2(arr);
- test3(arr2);
- test4(arr2);
- }
答案:T T T F T
二维数组传的是第一行元素的地址,二维数组本质上也是连续存放的,第一行后面跟着第二行。。。。。
- void test(int arr[3][5])// T
- {}
- void test(int arr[][])// F
- {}
- void test(int arr[][5])// T 行可以省略,列不能省略
- {}
- //二维数组传参,函数形参的设计只能省略第一个[]的数字。
- void test(int *arr)// F
- {}
- void test(int* arr[5])// F 是指针数组
- {}
- void test(int (*arr)[5])// T 数组指针
- {}
- void test(int **arr)// F 二级指针
- {}
- int main()
- {
- int arr[3][5] = {0};
- test(arr);
- }
- #include <stdio.h>
- void test()
- {
- printf("C++\n");
- }
-
-
- int main()
- {
- printf("%p\n", test);
- printf("%p\n", &test);//和数组不同,这两种都是函数地址
- return 0;
- }
- int Add(int x,int y)
- {
-
- return 0;
-
- }
函数返回类型为int,其参数为两个int元素,int (*pp) (int,int)=Add;pp就是函数指针变量
pp中存放的是Add地址,进行调用对其解引用*即可,(*pp)(num1,num2);
注意不要写成*pp(num1,num2)这种形式
但其实不对其解引用直接pp(num1,num2);也可以正常使用。*在此处并没有意义
写成*pp(1,2)这种形式就变成了*3,就会出现问题。
- //码1
- (*(void (*)())0)();
- //码2
- void (*evial(int , void(*)(int)))(int);
这两串代码是什么意思?
例1
例2
void ( *eva( int , void(*)(int) ) )(int);
void(*)(int)和int为eva( , )的两个参数的类型
eva的返回值类型为void(*)(int)
其形式比较复杂,我们可以通过typedef对其函数指针类型进行重命名
- typedef void(*pp)(int)//将函数指针类型void(*)(int)重命名为pp
- typedef void(*)(int) pp;//这种形式是错误的
- pp eva(int,pp)
后续会更新函数指针数组,指向函数指针数组的指针和回调函数qsort模拟实现。
感谢各位的阅读。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。