1.字符指针变量
1.1介绍
char arr[] = "abcdef";char* p = arr;
上面的代码中,我创建了 字符数组 arr 来存储一个字符串
此时,我可以创建一个指针变量对这个字符串进行相应的修改:
我也可以创建一个指针变量指向一个字符串:
char* p = "abcdef";
此时,p指向的是字符串首元素,即字符'a'
但值得注意的是:这是一个常量字符串
(1)定义:
常量字符串(Constant String)是指存储在程序内存中的一段不可修改的字符序列
(2)形式:
常量字符串通常使用双引号("")括起来,并自动在末尾添加一个空字符('\0')作为字符串的结束标志
此时,我不能通过指针变量,对该字符串进行修改:
程序能够编译通过,但是却会运行崩溃,编译器未显示错误
这是因为,上段代码的语法并未发生错误,只是规则不允许,导致程序崩溃
解决办法:使用const 进行修饰
const char* p = "abcdef";
这样编译器就会报错误,省去了自己去寻找错误的时间
总结:
(1)常量字符串不可被修改
(2)字符数组可以用来存储可修改的字符串
(3)字符指针指向一个常量字符串的时候,存储的是字符串首元素的地址
1. 2练习
void test()
{char str1[] = "hello zl_dfq.";char str2[] = "hello zl_dfq.";const char *str3 = "hello zl_dfq.";const char *str4 = "hello zl_dfq.";if(str1 ==str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");if(str3 ==str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");
}
解析:
创建了 str1 和 str2 两个字符数组
虽然两个数组存放的内容相同
很显然不同数组所占据的存储空间不同
所以数组首元素的地址不同(str1 != str2)
str3 和 str4 指向的是一个常量字符串
并且,字符串内容相同
因为常量字符串只能读,不能被修改
所以内存中没必要存储两份相同的常量字符串
所以,str3 == str4
2.数组指针变量
2.1引入
我们知道
整型指针是一种指针,它指向的是整型
字符指针是一种指针,它指向的是字符型
所以
数组指针是一种指针,它指向的是数组
这是一个指针数组
表达的含义是该数组存放着10个 int* 类型的指针
int * p[10];
这是一个数组指针
表达的含义是该指针指向一个类型为 int [10] 的数组
int (*p)[10];
记忆::[]的优先级要⾼于*,所以必须加上()来保证p先和*结合
如果不加(),标识符会先与[]结合,构成一个数组
2.2初始化
数组指针,指向的是一个数组,就是要存储一个数组的地址
程序运行证明,初始化正确!
(+1 操作后,地址相同)
3.二维数组传参的本质
void test(int arr[3][2])
{arr[0][0] = 10;printf("%d\n", arr[0][0]);
}
int main()
{int arr[3][2] = { {1,2},{3,4},{5,6} };printf("%d\n", arr[0][0]);test(arr);return 0;
}
观察上面的代码,
传入二维数组的数组名之后,我们就可以根据数组名,对二维数组的内容进行相应的修改
(1)
所以:我们传入的是一个(数组名)地址,
这是一个二维数组首元素的地址
而函数则是用一个指针来接收这个地址
因为,只有这样函数才可以通过指针去修改二维数组中相应的值
那这个指针是什么类型呢?
我们知道,
二维数组的本质是:一维数组的数组
即,将一个个一维数组看作一个个元素
所以,二维数组首元素就是二维数组中的第一个一维数组
那么,二维数组首元素的地址就是第一个一维数组的地址
所以这是一个数组指针
void test(int (*arr)[2]);
void test(int arr[3][2]);
上面的代码就完全等效 ,验证如下:
void test(int (*arr)[2])
{arr[0][0] = 10;printf("%d\n", arr[0][0]);
}
int main()
{int arr[3][2] = { {1,2},{3,4},{5,6} };printf("%d\n", arr[0][0]);test(arr);return 0;
}
总结:
⼆维数组传参,形参的部分可以写成数组,也可以写成指针形式。