一、指针基础知识
1指针概念:指针是一个值为内存地址的变量
2格式:指针在使用前一定要有明确指向(初始化)
1)先声明再初始化
2)声明的同时初始化
int a,*p=&a;
注:关于指针p的三个相关的值
1) p,p里面存放着一个地址
2)*p,p指向的对象的值
3)&p,表示变量p本身的地址
3*的作用
1)定义指针变量的标志
2)解引用,去内容(间接访问操作符)
4指针的大小
指针的大小和类型是无关的,指针类型的变量在相同的平台下大小都是相同的
x86环境(32位平台)地址是32个bit位(4个字节),指针变量的大小是4个字节
x64环境(64位平台)地址是64个bit位(8个字节),指针变量的大小是8个字节
5指针变量类型的意义
1)指针类型决定对指针解引用操作能有多大的权限(一次能操作几个字节)
例如,char*的指针解引用访问1个字节,int*的指针解引用访问4个字节
2)指针类型决定指针向前(后)走一步有多大距离
sizeof()
例如,char*类型指针+1跳过1个字节,int*类型指针+1跳过4个字节
6void*指针
void*类型指针可以用来接受任意类型的地址
但void型指针不能直接进行指针的+-整数和解引用的运算
7指针运算
1)指针+-整数:偏移量
2)指针-指针:前提条件,相距元素个数
3)指针比较运算:地址值大小比较
8指针的传址调用
9二级指针
存放指针变量的地址
*ppa=&b//等价于pa=&b,*ppa访问的是pa
**ppa=30//等价于*pa=30,即a=30
总结:int a,*p=&a,**pp=&p;
若pp是二级指针,*pp等价一级指针p,**pp等价*p等价于a
二、指针与数组
1数组名就是数组首元素地址(除2个例外
例外:
1)sizeof(数组名)这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
2)&数组名,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)
注:整个数组的地址和首元素地址的值在数值上通常是一样的,但二者的含义不同,所代表的类型也不同,首元素地址类型为对应元素类型的指针(比如对于 int 数组就是 int * 类型),而整个数组地址的类型是数组类型的指针(例如对于 int[5] 数组就是 int (*)[5] 类型)。
二维数组的数组名a是行地址,a+i指向第i行,a[i]是第i行首元素的地址,不是元素的引用
2使用指针访问数组
3指针数组和数组指针
1)指针数组:存放指针类型的数组,相当于一次性声明多个指针
int* p[n];
2)数组指针:指向的是数组
int(*p)[n];
a[3][2]中,a实质上就是一个数组指针
4一维数组与指针
1)指向一维数组定义格式:
int a[10],*p=a;
int a[10],*p=&a[0];
2)注意事项
//数组名本身表示数组的首地址,是常量而不是变量,不能对数组名进行自增自减或赋值运算
//*p++和*(p++)等价【*和++同优先等级,右结合性;运算符从右往左计算】
*p++
和 *(p++)
在行为上是完全相同的,两者都先返回指针当前指向的值,然后递增指针。
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3};
int *p = arr;
// 使用 *p++
printf("Value: %d\n", *p++); // 输出 1
printf("Next value: %d\n", *p); // 输出 2
// 重置指针
p = arr;
// 使用 *(p++)
printf("Value: %d\n", *(p++)); // 输出 1
printf("Next value: %d\n", *p); // 输出 2
return 0;
}
//*(p++)和*( ++p)不等价
*(p++):先解引用当前的 p,然后递增 p。
*(++p):先递增 p,然后解引用新的 p。
#include <stdio.h>
int main() {
int arr[] = {1, 2, 3};
int *p = arr;
printf("Using p++:\n");
printf("Value: %d\n", *(p++)); // 输出 1
printf("Next value: %d\n", *p); // 输出 2
// 重置指针
p = arr;
printf("\nUsing ++p:\n");
printf("Value: %d\n", *(++p)); // 输出 2
printf("Current value: %d\n", *p); // 输出 2
return 0;
}
//(*p)++和*(p++)不等价
(*p)++:先解引用 p 获取其指向的值,然后递增该值。指针 p 本身没有变化。
*(p++):先解引用 p 当前指向的地址,获取该地址处的值,然后递增指针 p。被解引用的值不会改变,只是指针 p 移动到了下一个位置。
#include <stdio.h>
int main() {
int arr[] = { 10, 20, 30 };
int* p = arr;
printf("Using (*p)++:\n");
printf("Value before: %d\n", *p); // 输出 10
printf("Value after (*p)++: %d\n", (*p)++); // 输出 10 (后增++是返回递增前的值)
printf("Final value: %d\n", *p); // 输出 11 (实际值已递增)
printf("数组首元素现在的值是%d", arr[0]);//输出11
// 重置指针
p = arr;
printf("\nUsing *(p++):\n");
printf("Value before: %d\n", *p); // 输出 11【上面实际值已递增带来的影响】
printf("Value after *(p++): %d\n", *(p++)); // 输出 11 (解引用当前地址)
printf("Next value: %d\n", *p); // 输出 20 (指针已递增)
return 0;
}
3)一维数组元素输入输出
指针移动法
请注意第二个for循环要重置指针让它指到a,因为在第一个 for 循环结束后,p 已经指向 a + 10,即数组 a 的末尾。如果不加上p=a则第二个 for 循环的条件 p < a + 10 永远为假,循环体不会执行。
5二维数组与指针
1)指向二维数组定义格式:
int a[3][4],*p;
p=&a[0][0];
或者
p=a[0];
2)行指针:指向行数组的指针变量
int a[3][4];
int (*p)[4]=a;
行指针p被赋予a后,p可以当作二维数组名p[i][j]使用
3)二维数组的元素地址
二维数组a[m][n]中:
元素a[i][j]的几种表示形式
//&a[i][j]
//a[0]+n(具体看几列)*i+j【依赖于数组的实际布局。
//a[i]+j
//*(*(a + i) + j)
*(a + i):解引用 a + i,得到第 i 行的地址。
【二维数组中a[i]表示第i行首元素的地址】
*(a + i) + j:将第 i 行的指针向前移动 j 个位置,指向第 i 行第 j 列元素。
*(*(a + i) + j):最终解引用 *(a + i) + j,得到第 i 行第 j 列的元素值。
三、函数与指针(主要是函数参数传递)
传数组xx xxx(int *arr)或者xx xxx(int arr[])
四、字符串与指针
1字符指针变量
char *str2="abc";
定义一个字符型指针变量,占用1个指针型存储单元,另分配4个连续的字符型存储单元存放“abc”,其首地址存放在指针变量str2中
2字符指针数组和二维字符数组
标签:复习,++,----,int,地址,数组,printf,指针 From: https://blog.csdn.net/2401_86517033/article/details/144625646