当前位置:网站首页>指针进阶简单总结
指针进阶简单总结
2022-07-17 05:07:00 【Yuan_o_】
- 指针是什么?
内存 --> 内存的单元(1byte) --> 编号 --> 地址 --> 指针
所以指针就是一个地址
口头语中说的指针一般是指:指针变量
指针变量就是一个变量,就是一块内存空间,指针变量用来存放地址
#include <stdio.h>
int main()
{
int a = 10;
int* pa = &a;//pa是一个指针变量,而不是*pa
*pa = 20;//在这里*是解引用操作符,找到pa指针变量所指的内存空间
printf("%d\n", a);
return 0;
}
指针变量的大小:4/8个字节
- 指针类型的意义?
- 指针在执行+1/-1操作的时候,跳过几个字节(步长)
- 解引用操作的时候的权限
- 指针的运算
- 指针 ± 整数
- 指针 - 指针
- 指针的关系运算
- 指针数组
指针数组本质上就是数组,数组中存放的是指针(地址)
int* pa;
int* pb;
int* pc;
int* arr[3] = {
pa,pb,pc };//指针数组
- 数组名是什么?
- 数组名在大部分情况下表示数组首元素的地址
- 有两个例外(取出的是整个数组的地址):sizeof(数组名);&数组名
- 数组指针
int arr[10] = {
1,2,3 };
int(*parr)[10] = &arr;//parr是数组指针
- 函数指针
int main()
{
//函数的地址存放到函数指针变量中
int (*pf)(int, int) = &Add;//pf是函数指针
int (*pf)(int, int) = Add;//两种方法均可
int sum = (*pf)(2, 3);//两种方法均可
int sum = pf(2, 3);
printf("%d\n", sum);
return 0;
}
- 存放函数指针的数组
int(*pf)(int, int);//函数指针
//指针名:pf;指针指向函数的参数为(int, int);指针返回值类型为int
int(*pfarr[4])(int, int);//函数指针数组
//数组名:pfarr;数组大小:4;数组每个元素的类型:int(*)(int, int)
- 回调函数
回调函数是一个通过函数指针调用的函数
指针详解
//一维数组(区分元素地址和元素大小)
int a[] = {
1,2,3,4 };
printf("%d\n", sizeof(a));//16
//sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小,单位是字节
printf("%d\n", sizeof(a + 0));//4(在32位平台下)
//a不是单独放在sizeof内部,也没有取地址,所以a就是首元素地址,a+0还是首元素地址
//是地址,大小就是4/8个字节。 a <==> &a[0] ; a+0 <==> &a[0]+0
printf("%d\n", sizeof(*a));//4
//*a中的a是数组首元素的地址,*a就是对首元素解引用,找到的就是首元素
//首元素的大小就是4字节
printf("%d\n", sizeof(a + 1));// 4/8
//这里的a是数组首元素的地址
//a+1是第二个元素的地址
//sizeof(a+1)就是地址的大小
printf("%d\n", sizeof(a[1]));//4
//计算的是第二个元素的大小
printf("%d\n", sizeof(&a));//4/8
//&a取出的是数组的地址,数组的地址,也是地址
printf("%d\n", sizeof(*&a));//16
//&a --> int(*)[4]
//&a拿到的是数组名的地址,类型是 int(*)[4],是一种数组指针
//数组指针解引用找到的是数组
//&和*抵消了
//*&a --> a
printf("%d\n", sizeof(&a + 1));// 4/8
//&a取出的是数组的地址
//&a --> int(*)[4]
//&a+1 是从数组a的地址向后跳过了一个(4个整型元素的)数组的大小
//&a+1 还是地址,是地址就是4/8个字节
printf("%d\n", sizeof(&a[0]));// 4/8
//&a[0]就是第一个元素的地址
//计算的是地址的大小
printf("%d\n", sizeof(&a[0] + 1));// 4/8
//&a[0] + 1 是第二个元素的地址
//大小是4/8个字节
//&a[0] + 1 --> &a[1]
//sizeof 是操作符,只关注占用内存空间的大小,不在乎内存中放的是什么
//strlen 是库函数,只针对字符串,是求字符串的长度的,关注的是字符串中的\0,计算的是\0之前出现的字符的个数
//字符数组
char arr[] = {
'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));//6
//sizeof(数组名)
printf("%d\n", sizeof(arr + 0));// 4/8
//arr + 0 是数组首元素的地址
printf("%d\n", sizeof(*arr));// 1
//*arr就是数组首元素,大小是1字节
//*arr --> arr[0]
//*(arr+0) --> arr[0]
printf("%d\n", sizeof(arr[1]));// 1
printf("%d\n", sizeof(&arr));// 4/8
//&arr是数组的地址,是地址就是4/8个字节
printf("%d\n", sizeof(&arr + 1));// 4/8
//&arr + 1是数组后的地址
printf("%d\n", sizeof(&arr[0] + 1));// 4/8
//&arr[0] + 1是第二个元素的地址
printf("%d\n", strlen(arr));//随机值
//数组里面没有\0,所以他会向后一直找,直到找到\0为止
printf("%d\n", strlen(arr + 0));//随机值
printf("%d\n", strlen(*arr));//
//strlen(*arr) --> strlen('a') --> strlen(97);
//相当于把97这个地址传给了strlen,97这个地址不能随便用,属于野指针,非法
printf("%d\n", strlen(arr[1]));
//strlen(arr[1]) --> strlen('b') --> strlen(98);野指针
printf("%d\n", strlen(&arr));//随机值。
//因为传给strlen的类型都转换为char*,所以虽然arr和&arr的类型不一样,但是随机值是一样的
printf("%d\n", strlen(&arr + 1));//随机值-6,因为他跳过了数组(数组6个元素)
printf("%d\n", strlen(&arr[0] + 1));//随机值-1,因为他跳过了一个字节
char arr[] = "abcdef";
// { a b c d e f \0 }
printf("%d\n", sizeof(arr));//7
printf("%d\n", sizeof(arr + 0));// 4/8
printf("%d\n", sizeof(*arr));//1
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));// 4/8
printf("%d\n", sizeof(&arr + 1));// 4/8
printf("%d\n", sizeof(&arr[0] + 1));// 4/8
printf("%d\n", strlen(arr));//6
printf("%d\n", strlen(arr + 0));//6
//arr+0,依旧是首元素,从首元素开始计算,直到\0位置
printf("%d\n", strlen(*arr));//err
printf("%d\n", strlen(arr[1]));//err
printf("%d\n", strlen(&arr));//6
//&arr是整个数组的地址,依旧是从首元素开始的
printf("%d\n", strlen(&arr + 1));//随机值
//&arr是整个数组的地址,&arr+1跳过了整个数组(包括\0)
//数组后面存的是什么不知道,不知道下一个\0在哪,所以是随机值
printf("%d\n", strlen(&arr[0] + 1));//5
//&arr[0]是首元素地址,&arr[0] + 1从第二个元素开始直到\0为止
char* p = "abcdef";//{ a b c d e f \0 }
//把首字符a的地址放到p中
printf("%d\n", sizeof(p));// 4/8
printf("%d\n", sizeof(p + 1));// 4/8
printf("%d\n", sizeof(*p));//1
printf("%d\n", sizeof(p[0]));//1
//p[0] --> *(p+0) --> *(p)
printf("%d\n", sizeof(&p));// 4/8
printf("%d\n", sizeof(&p + 1));// 4/8
printf("%d\n", sizeof(&p[0] + 1));// 4/8
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p + 1));//5
printf("%d\n", strlen(*p));//err
printf("%d\n", strlen(p[0]));//err
printf("%d\n", strlen(&p));//随机值
printf("%d\n", strlen(&p + 1));//随机值
//这个随机值和上一个随机值不是-1的关系
//因为p的地址是4个字节,有可能在p内部有一个\0
//这种情况下,两个随机值没有任何关系
printf("%d\n", strlen(&p[0] + 1));//5
//二维数组
int a[3][4] = {
0 };
printf("%d\n", sizeof(a));//3*4*4=48 算出的是整个数组的大小
printf("%d\n", sizeof(a[0][0]));//4
printf("%d\n", sizeof(a[0]));//4*4=16
//a[0]是第一行这个一维数组的数组名,单独放在sizeof内部,a[0]表示第一行整个一维数组
//sizeof(a[0])计算的就是第一行的大小
printf("%d\n", sizeof(a[0] + 1));// 4/8
//a[0]并没有单独放在sizeof内部,也没有取地址,a[0]就表示首元素的地址
//就是第一行这个一维数组的第一个元素的地址
//a[0]+1 <==> a[0][0]+1 表示第一行第二个的元素的地址
printf("%d\n", sizeof(*(a[0] + 1)));//4
//a[0]+1就是第一行第二个元素的地址
//*(a[0]+1)就是第一行第二个元素,类型为int,所以是四个字节
printf("%d\n", sizeof(a + 1));// 4/8
//a虽然是二维数组的地址,但是并没有单独放在sizeof内部,也没取地址
//a表示首元素的地址,二维数组的首元素是它的第一行,a就是第一行的地址
//a+1就是跳过第一行,表示第二行的地址
printf("%d\n", sizeof(*(a + 1)));//16
//*(a+1)是对第二行地址的解引用,拿到的是第二行
//*(a+1) --> a[1]
//sizeof(*(a+1)) --> sizeof(a[1])
printf("%d\n", sizeof(&a[0] + 1));// 4/8
//&a[0] 是对第一行的数组名取地址,拿出的是第一行的地址
//&a[0]+1 得到的是第二行的地址
printf("%d\n", sizeof(*(&a[0] + 1)));//16
//第二行的大小
printf("%d\n", sizeof(*a));//16
//a表示首元素的地址,就是第一行的地址
//*a就是对第一行的地址解引用,拿到的就是第一行
printf("%d\n", sizeof(a[3]));//16
//虽然二维数组没有第四行
//但是sizeof只要知道类型就可以计算大小,并不会真的访问第四行,不会越界访问
总结:
数组名的意义:
- sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
- &数组名,这里的数组名表示整个数组,取出的是指整个数组的地址。
- 除此之外所有的数组名都表示首元素地址。
边栏推荐
猜你喜欢
随机推荐
【C语言—零基础_学习_复习_第五课】基本运算符的运算性质
Excel导入长数据末尾变000
Addition and removal of cesium geojson data
MySQL optimization
实习项目3-更改所有者
es6新增-运算符的扩展
es6新增-数组部分
Internship project 1 - personalized homepage configuration
Cesium geojson数据的添加与移除
Email (including attachments, Netease, QQ)
这么6的刷题网站你不会没听说过吧?你已经out 了?
【Es6】forEach,for... in ,for... Of column, which allows you to quickly distinguish the usage and differences of various for statements through project cases (full version). There are detailed notes ins
Internship project 3- change owner
【C语言—零基础第六课】输入输出语句格式与复合语句
<script>标签内容详解
Teddy Cup title a full version optimization update (4/23)
uniapp 表单(input、radio、picker)提交获取参数值
使用js中的(offset,page)实现登录效果
UML(用例图,类图,对象图,包图)
ThreadLocal thread safety example and its principle









