指针解引用等价于指针取下标
#include<stdio.h>
int main(){
int arr[] = {10,20,30,40,50,60,70,80};
int *p = arr;
//输出*(p+1)+6 *(p+1) = 20
printf("*(p+1)+6 = %d\n",*(p+1)+6);
printf("result = 26\n");
//输出p[1]+6 p[1] = 20
printf("p[1]+6 = %d\n",p[1]+6);
printf("result = 26\n");
return 0;
}
要注意的是千万不要将p[1] + 6 写成 *(p[1] + 6),对指针取下标的时候就相当于解引用的效果,直接获取对应存储区所存储的值
二级指针
一级指针(例如 int *p
)是一个存储地址的变量,该地址指向某个类型的数据。二级指针(例如 int **pp
)是一个存储一级指针地址的变量。也就是说,二级指针指向一个指针,而这个指针又指向一个具体的数据。二级指针和一级指针一样都可以通过解引用直接修改存储区的值。
#include<stdio.h>
int main(){
int a = 10;
int* p = &a;
int** pp = &p;
printf("a = %d &a = %p\n",a,&a);
printf("p = %p &p = %p\n",p,&p);
printf("pp = %p &pp = %p\n",pp,&pp);
printf("*p = %d\n",*p);
printf("*pp = %p\n",*pp);
printf("**pp = %d\n",**pp);
//通过一级指针修改所指向存储区的值
*p = 11;
printf("a = %d\n",a);
//通过二级指针修改所指向存储区的值
**pp = 12;
printf("a = %d\n",a);
return 0;
}
字符数组与二维数组
为什么多个数字可以用一维数组存储,但换成字符串就不可以???
首先你要知道:数字和字符串的存储方式有本质的区别
一维数组存储数字
当你声明一个一维数组来存储数字时,每个数组元素都是一个固定大小的内存块。例如:
int arr[3] = {1, 2, 3};
在这种情况下,数组arr
中的每个元素都是一个整数,每个整数占用固定的内存大小(通常是4个字节,具体取决于平台)。
一维数组存储字符串
字符串在C语言中是由字符数组表示的。每个字符串本质上是一个字符数组,以空字符\0
结尾来标识字符串的结束。
存储单个字符串
存储单个字符串时,可以使用一维字符数组:
char str[] = "Hello";
在这种情况下,str是一个字符数组,包含字符串"Hello"以及终止符\0
。
存储多个字符串
存储多个字符串时,使用一维数组是不可行的,因为不同字符串的长度可能不同,且每个字符串需要独立存储,以终止符\0
标识结束。
使用二维字符数组存储多个字符串
为了存储多个字符串,需要使用二维字符数组或字符指针数组。
char arr[2][10] = {"Hello", "World"};
在这种情况下,arr
是一个二维字符数组,其中每个元素都是一个字符数组。每个字符串存储在一个单独的字符数组中,并以空字符\0
结尾。内存布局如下:
| H | e | l | l | o | \0| | | | |
| W | o | r | l | d | \0| | | | |
使用字符指针数组存储多个字符串
另一种方式是使用字符指针数组:
char *arr[] = {"Hello", "World"};
在这种情况下,arr
是一个字符指针数组,其中每个指针指向一个字符串常量。
总结
- 数字:每个数字占用固定大小的内存块,因此可以用一维数组直接存储。
- 字符串:每个字符串的长度可能不同,需要以空字符
\0
结尾来标识结束。为存储多个字符串,可以使用二维字符数组(每个字符串占用固定大小的字符数组)或字符指针数组(每个指针指向一个字符串常量)。
数字的一维数组
#include <stdio.h>
int main() {
int arr[3] = {1, 2, 3};
for (int i = 0; i < 3; i++) {
printf("%d\n", arr[i]);
}
return 0;
}
字符串的二维字符数组
#include <stdio.h>
#include <string.h>
int main() {
char arr[2][10] = {"Hello", "World"};
for (int i = 0; i < 2; i++) {
printf("%s\n", arr[i]);
}
return 0;
}
字符串的字符指针数组
#include <stdio.h>
int main() {
char *arr[] = {"Hello", "World"};
for (int i = 0; i < 2; i++) {
printf("%s\n", arr[i]);
}
return 0;
}
我在首次使用字符指针数组时,我最开始的时候很疑惑为什么printf的参数使用arr[i]而不应该是解引用*arr[i]吗???
解引用字符指针
实际上,arr[0]
本身就是一个指向字符串的指针。你可以将 arr[0]
视为指向字符数组的指针,其类型是 char *
。
当你解引用字符指针时,得到的是该指针指向的第一个字符。例如:
#include <stdio.h>
int main() {
char *arr[] = {"Hello", "World", "C Programming"};
// 输出第一个字符串的第一个字符
printf("%c\n", *arr[0]); // 解引用arr[0]得到第一个字符
return 0;
}
在这段代码中:
*arr[0]
解引用arr[0]
得到的是字符'H'
。printf("%c", *arr[0]);
使用%c
格式说明符输出字符'H'
。
总结
- 使用
%s
格式说明符时,printf
会将参数解释为字符指针,并打印该指针指向的字符串。 - 直接使用
arr[0]
作为printf
的参数是有效的,因为arr[0]
本身就是一个字符指针。 - 如果你解引用
arr[0]
,得到的是该指针指向的第一个字符。
对于这个问题:我在首次使用字符指针数组时,我最开始的时候很疑惑为什么printf的参数使用arr[i]而不应该是解引用*arr[i]吗???
printf
函数的%s
格式说明符用于打印字符串,它要求传入一个指向以null结尾的字符数组(即字符串)的指针。而*arr[0]
实际上是arr[0]
指向的字符串的第一个字符,类型是char
,不是指向字符串的指针。因此,当你使用printf("%s\n", *arr[0]);
时会报错,因为%s
期望的是一个char*
类型的参数,而不是char
类型。要打印字符串 "Hello"
,你应该直接使用arr[0]
作为参数传递给printf
,因为arr[0]
本身就是指向 "Hello"
的指针。