一、二级指针
通过前面的学习我们可以知道,指针变量也是变量,是存放地址的变量,那既然是变量,就会有地址,指针变量的地址又存放在哪里呢?
还是存放在指针里面,这就是二级指针。
int main() {
int a = 10;
int* p = &a;
int** pa = &p;
}
pa就是存放指针变量p的指针,也就是二级指针。
那么对二级指针的解引用的效果是什么呢?
对于pa的解引用后,里面存放的地址是p的地址,也就说*pa其实是去访问p。
那**pa是去访问谁呢?我们一层一层的看:
**pa是对(*pa)解引用,刚刚我们知道了*pa访问的是p,所以**pa实际上是对p的解引用,对p的解引用访问的是a。
所以:**pa是去访问a
(这样可以无限套娃,但这样对于程序还是写代码的人来说都是很大负担,尽量不要多套的使用指针,意义并不算大)
二、指针数组
指针数组是指针还是数组?
我们可以类比一下,整数数组是存放整数的数组,字符数组是存放字符的数组,以此类推,指针数组就是存放指针的数组。
所以指针数组是数组。
该数组中的每一个元素都是用来存放地址(指针),这些元素又各种指向各种的位置。
用指针数组去模拟二维数组
我们知道二维数组的一些特性,结合刚刚学习的指针数组,代码如下:
int main() {
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 2,3,4,5,6 };
int arr3[] = { 3,4,5,6,7 };
int* parr[] = { arr1,arr2,arr3 };
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
printf("%d ", parr[i][j]);
}
printf("\n");
}
return 0;
}
parr[i]是访问数组parr中的元素,而parr中存放的是一维数组的地址,所以parr[i][j]就是整型一维数组中的元素。
用上述代码就可以实现出来二维数组的效果,但是这并非是真正的二维数组,我们知道数组中的元素都是连续的,高维数组也不例外,但用parr实现的“二维数组”中,每一行并非是连续的。
提问:为什么parr[i][j]就可以表示整型一维数组中的元素呢,我们定义parr的时候他也是一维数组呀,为什么还有【j】呢?
我们在上一节了解过 *(arr + i)是等价于 arr[i],以此我们可以把
arr[i][j] 等价于 *(*(arr + i)+ j)
所以对于计算机来说,arr[i][j] 和 *(*(arr + i)+ j)是一样的,但是为了便于程序员的理解容易,写成arr[i][j] 。
三、字符指针变量
char*
int main() {
char ch = 'z';
char* pc = &ch;
*pc = 'z';
const char* pstr = "sllh sllr";
printf("%s\n", pstr);
return 0;
}
使用一般为上面两种方式
需要注意的是:
const char* pstr = "sllh sllr";
并不是吧 sllh sllr 这个字符串放进了字符指针pstr中了,其实是把字符串的首字母的地址放在了指针当中。
看看下面这段代码,输出的结果是什么呢?
int main() {
char str1[] = "sllh sllr";
char str2[] = "sllh sllr";
const char *str3 = "sllh sllr";
const char *str4 = "sllh sllr";
if (str1 == str2)
printf("1 and 2 are same\n");
else
printf("1 and 2 are not same\n");
if(str3 == str4)
printf("3 and 4 are same\n");
else
printf("3 and 4 are not same\n");
return 0;
}
1和2 不同 3和4相同
这是为什么呢?明明1,2,3,4的内容都是一样的呀
这是因为在c/c++中会把常量字符串存储在一个单独的内存区域,当不同的指针(str3和str4)指向同一个字符串时,实际会指向同一个内存,两者中存储的地址也就是相同的,所以str3 == str4。
但是对于数组的初始化来说,哪怕两个数组的内容完全一样,依旧会开辟两个不同的空间去分别存储这两个数组,这就导致数组str1和数组str2指向的地址不同,所以str1 != str2。
(内容相同的常量字符串只会保存一份,哪怕多次定义)
以后学习总结的内容封面就都用这个吧
一直用C语言当封面好单调(坏笑)