目录
1指针的大小
指针是一种特殊的变量,用于存储内存地址。可以直接访问内存中的数据,而无需知道变量的名称。指针变量包含一个内存地址,该地址指向存储在计算机内存中的数据位置。
指针的大小即地址的大小,地址是物理的电线上产生的,对于32位机器,有32根地址线,即有32个1和0组成的二进制序列,这个二进制序列就叫做地址,需要32个比特位才能存储这个地址。许多32位操作系统上,指针通常是4个字节(32位),而在64位操作系统上,指针通常是8个字节(64位)。
虽然指针的大小都是4/8字节,但指针仍有许多类型,不同类型对应的指针在存放、解引用、指针运算上有差异。
2指针类型
2.1字符指针
字符指针是指向字符数据的指针,在处理字符串和字符数组中有重要作用。
字符指针的用途包括但不仅限于:
2.1.1指向字符串常量
char *strPtr = "Hello, world!";
要注意,这里不是把一个字符串放到strPtr指针变量里了,本质是把字符串"Hello World"的首字符的地址放到了strPtr中。
有一道面试题考察了这个知识点:
#include <stdio.h>
int main()
{
char str1[] = "hello world.";
char str2[] = "hello world.";
char *str3 = "hello world.";
char *str4 = "hello world.";
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");
return 0;
}
运行结果:
str1 and str2 are not same
str3 and str4 are same
数组名是首地址,str1和str2的首地址不一样,所以str1和str2显然不相等;*str3和*str4都指向了同一个字符串,两个字符指针存放的地址是相同的,所以是str3和str4是相同的。
2.1.2指向字符数组
char str[] = "Hello";
char *strPtr = str;
2.1.3访问字符串
printf("%s", strPtr);
2.1.4使用指针遍历字符串
while (*strPtr != '\0') {
printf("%c", *strPtr);
strPtr++;
}
字符指针在中经常用于字符串的处理和操作,例如字符串的拷贝、比较、连接等。这些功能包含在string.h中,详见:cplusplus.com/reference/cstring/?kw=string.h
2.2指针数组
指针数组,即存放指针的数组。数组的每一个元素都是一个指针类型的变量。示例如下:
int *p[10];
这里要注意: [] 的优先级要高于 * 的,所以 p 先与 [] 结合,说明他的一个存放10个变量的数组,而数组的每一个变量类型是 int*。
数组指针的使用:
指针数组的使用场景很多,其中一个典型的用法是处理字符串数组。比如:
#include <stdio.h>
int main() {
char *strings[] = {"apple", "banana", "orange"};
for (int i = 0; i < 3; i++) {
printf("%s\n", strings[i]);
}
return 0;
}
还可以通过指针数组来模拟实现二维数组:
#include <stdio.h>
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[3] = { arr1, arr2, arr3 };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
2.3数组指针
数组指针,即指向数组的指针。与指针数组不同,数组指针指向的是一个完整的数组,而不是数组中的单个元素。示例如下:
int (*p)[10];
由于 () 优先级最高,所以 p 先与 * 结合,说明他是一个指针,指向的是一个大小为10,元素类型为int的数组。
数组指针的一个重要运用就是传递多维数组给函数
#include<stdio.h>
void printArray(int (*arr)[3], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", arr[i][j]);
//也可以写为:printf("%d ", *(*(arr + i) + j));
}
printf("\n");
}
}
int main() {
int arr[2][3] = {
{1, 2, 3}, {4, 5, 6}};
printArray(arr, 2);
return 0;
}
二维数组的数组名表示二维数组第一行的地址,是一个一维数组的地址,类型为数组指针。所以这里 printArray 函数接收的是二维数组第一行的地址,通过arr[i][j]的方式来访问arr数组的第i行第j个元素。
2.4函数指针
函数指针可以用来存储函数的地址,使得可以动态地选择调用不同的函数,从而实现一些高级的编程技巧和模式。
若定义有:int add(int x, int y)
则int (*p)(int int) --> p 就是函数指针变量
2.4.1来看两段代码
(*(void (*)())0)()
从里层括号开始看:
- void(*)()是函数指针类型
- 括号里面放类型 就相当于 强制类型转换,相当于将0(地址处)强制