1.字符指针变量
//int main() //{ // char ch = 'w'; // char*pc=&ch; // printf("%c", *pc); // return 0; //} /*int main() { //char* p = "abcdef"; //char arr[] = "abcdef";//常量字符串 a b c d e f \0 //char* pc = arr;//将数组首元素的地址存在p中 const char* p = "abcdef";//这里的赋值是讲字符串中首字符的地址存在p中 printf("%c\n", *p);//打印a //如何打印一整个字符串呢? printf("%s\n", p);//使用%s打印字符串的时候,只需要提供首字符的地址就行了 //*p='q'------不允许修改,因为p指向的是常量字符串,常量字符串不能被修改 //在5303行添加const可以防止*p被修改 return 0; }*/ int main() { char str1[] = "hello bit."; char str2[] = "hello bit."; const char* str3 = "hello bit."; const char* str4 = "hello bit."; 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是一个数组,只是内容相同而已 "hello bit."是一组常量字符串,是不能被修改的 内容相同的常量字符串只需要保存一份就可以 str3和str4存的都是h的地址,两个指针变量各自指向同一个地址 在这个条件语句中if (str1 == str2) str1是数组名,首元素的地址,str2也是数组名,也是首元素的地址 str1和str2各占两份不同的空间,只是内容一样 完全不同的两个空间 在这个条件语句中if (str3 == str4) str3和str4存放的都是h的地址,存放的是同一个地址 所以二者相同 这个代码里面的比较,不是比较字符串,比较的是地址 */
使用%s打印字符串的时候,只需要提供首字符的地址就行了
char* p = "abcdef";//这里的赋值是讲字符串中首字符的地址存在p中
2.数组指针变量
指针数组--是数组--存放的是指针(地址)
数组指针是什么呢?
类比:字符指针--char*---指向字符的指针--字符指针变量中存放字符的地址
char ch='w';
char *pc=&ch;
整型指针---int*--指向整型的指针--整型指针变量中存放的整型变量的地址
int a=10
int *p=&a
那么数组指针就是指向数组的指针
数组指针变量存放的是数组的地址
数组的地址--&数组名
指针数组
1.是数组
2.是存放指针的数组
char* arr[6]-----char*是数组的元素类型---存放字符串指针的数组
int *arr2[5]---存放整型指针的数组
数组指针
是指针,指向数组的指针
*p--表示这是一个指针变量
这个指针指向的是数组,得有大小[10]
(*p)[10]
数组指向的元素类型是什么呢?在前面加上类型
int (*p)[10]--这里的p就是数组指针,P指向的数组有10个元素,每个元素的类型是int
p的类型是int (*)[10]
将数组的地址取出来,存放在指针变量里面,
char(ptr)=&arr---arr里面都是char类型的
//指针数组 //int main() //{ // int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; // int(*p)[10] = &arr;//取出的是数组的地址,那么数组的地址就应该放到数组指针里面 // // //想使用p这个数组指针访问arr数组的内容 // //p里面放的是数组的地址,那么*p就相当于拿到了一个数组 // for (int i = 0; i < 10; i++) // {//*p就是数组,那么咱们加上[i]就说明直接访问arr[i],随着i的变化,逐步打印数组内的内容 // printf("%d", (*p)[i]); // } // return 0; //} //上面这种就显得有点麻烦 //int main() //{ // //int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; // //int(*p)[10] = &arr;//取出的是数组的地址,那么数组的地址就应该放到数组指针里面 // // 想使用p这个数组指针访问arr数组的内容 // p里面放的是数组的地址,那么*p就相当于拿到了一个数组 // //for (int i = 0; i < 10; i++) // //{//*p就是数组,那么咱们加上[i]就说明直接访问arr[i],随着i的变化,逐步打印数组内的内容 // // printf("%d", (*p)[i]); // //} // int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; // int* p = arr; // for (int i = 0; i < 10; i++) // { // printf("%d",p[i]);//p就是首元素的地址 p[i]---*(p+i) // } // // // return 0; //}
3.二维数组传参的本质
不管是一位数组还是二维数组传参,形参可以写成数组,也可以写成指针
这里要对数组名做一个深入的理解
咱们要考虑到arr是数组首元素的地址
数组名+i就是跳过i个数组
arr[i]-----(arr+i)---第i行 arr[i][j]-----((arr+i)+j)---(arr+i)是第i行首元素的地址,+j就表示下标为j的数字的地址,再解引用就能得到下标为j的数字
对于一个二维数组的话,arr是数组名,同时也是这个二维数组第一行的元素地址
arr+i就是这个二维数组第i行的地址
对于(*(arr + i))[j]的理解
*(arr + i)就是这个二维数组的第i行的地址解引用得到第i行
[j]这个就是第i行下标为j的元素
对于((arr + i)+j)的理解
*(arr + i)是第i行首元素的地址,这个首元素的地址+j就是第i行下标为j的数字的地址,
*(arr + i)+j再将其解引用得到的就是第i行下标为j的元素
//二维数组传参的本质 /*void print(int arr[3][5], int r, int c) { //两层循环,第一层循环打印行,第二层循环打印列 for (int i = 0; i < r; i++) { for (int j = 0; j < 5; j++) { printf("%d ", arr[i][j]);//打印一行的内容 } printf("\n");//换行 } } int main() { int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7} }; print(arr, 3, 5);//将arr数组的内容打印出来,数组名、行和列都要传上去 return 0; }*/ //一维数组传参 /*数组名是首元素的地址 * 一维数组在传参的时候,其实传递的是首元素的地址 * * 函数的参数可以写成数组,也可以写成指针 * * 那么二维数组呢? * 二维数组的数组名该如何理解呢? * 其实二维数组的数组名也是数组首元素的地址,但是是那个数字呢? 二维数组可以理解为一维数组的数组 将二维数组里面的三个一维数组当成一个元素 二维数组有三个元素,每个元素有三个数组 二维数组的每一行可以看成是一个一维数组‘二维数组的首元素就是这个二维数组的第一行 二维数组的数组名就是第一行的地址 不是第一行首元素的地址,而是第一行整个一维数组的地址 */ void print(int(*arr)[5], int r, int c)//因为传过来的是一位数组的地址,我们要用数组指针接收 //使用数组指针存放第一行的地址,传过来的是一个一维数组,那么我们就需要一个数组指针来接收 {//这个数组指针并不是指向的二维数组,而是指向的是这个二维数组的第一行 //两层循环,第一层循环打印行,第二层循环打印列 for (int i = 0; i < r; i++) { for (int j = 0; j < 5; j++) { //第一行是arr //第二行是arr+1 printf("%d ", (*(arr + i))[j]);//arr+i就是第几行,*(arr + i)就是解引用相当于直接访问数组后面的[j]就是那一行一维数组里面的第几个元素 } //printf("%d ", *(*(arr + i)+j)) //arr+i是某一行的地址,将其括起来解引用就是这一行,相当得到第i行的数组名 // *(arr+i)==arr[i],arr[i]是第i行的数组名,数组名是数组首元素的地址 // *(arr + i)数组首元素的地址+j就是这一行首元素后面第j个元素的地址,再解引用 // 再将这个地址解引用得到的就是数组首元素 // *(arr + i)一行首元素的地址再+j就是下标为j的元素了 // 对于这个二维数组,arr[i]表示的是arr[i][0],第i行第1个元素的地址 // // //*(arr + i)这个是某一行,相当于拿到这一行的数组名字 //对于二维数组arr的话 //arr[0]是第一行的数组名 //arr[1]是第二行的数组名 printf("\n");//换行 } } int main() { int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7} }; print(arr, 3, 5);//将arr数组的内容打印出来,数组名、行和列都要传上去 //arr是在这个二维数组首元素的地址,是第一行的地址,第一行是一位数组 //这里传过去的是第一行的地址 return 0; } /*不管怎么写对于二维数组arr+i就是这个二维数组的第i行一维数组, * 传参时的arr是二维数组第一行, * * 数组名+i就是跳过一整个数组,对于二维数组,里面是存在好几个一维数组的 对于(*(arr + i))[j]的理解 *(arr + i)就是这个二维数组的第i行的地址解引用得到第i行 [j]这个就是第i行下标为j的元素 对于*(*(arr + i)+j)的理解 *(arr + i)是第i行首元素的地址,这个首元素的地址+j就是第i行下标为j的数字的地址, *(arr + i)+j再将其解引用得到的就是第i行下标为j的元素 arr[i]-----*(arr+i)---第i行 arr[i][j]-----*(*(arr+i)+j)---*(arr+i)是第i行首元素的地址,+j就表示下标为j的数字的地址,再解引用就能得到下标为j的数字 */
*(*(arr+i)+j)
是访问二维数组中第i
行,第j
列元素的方法。
在C语言中,二维数组可以看作是由多个一维数组组成的连续存储空间。定义一个 int
类型的二维数组 arr
,用 arr[i][j]
表示其第 i
行、第 j
列的元素,也可以写成 *(*(arr+i)+j)
。
解释 *(*(arr+i)+j)
的过程如下:
arr
是一个指向二维数组首地址的指针,*(arr+i)
表示访问第i
个一维数组的首地址。*(arr+i)+j
表示在第i
个一维数组的基础上向后移动j
个位置,即访问第i
行、第j
列元素的地址。*(*(arr+i)+j)
表示访问上述地址所存储的值,即获取第i
行、第j
列的元素值。
(*(arr + i))[j]
也可以用来访问二维数组中第 i
行,第 j
列的元素。
在C语言中,二维数组可以看作是由多个一维数组组成的连续存储空间。定义一个 int
类型的二维数组 arr
,用 arr[i][j]
表示其第 i
行、第 j
列的元素,也可以写成 *(*(arr+i)+j)
或 (*(arr + i))[j]
。
解释 (*(arr + i))[j]
的过程如下:
arr
是一个指向二维数组首地址的指针,*(arr + i)
表示访问第i
个一维数组的首地址。(*(arr + i))[j]
表示使用[]
运算符访问该一维数组中下标为j
的元素,即获取第i
行、第j
列的元素值。
C语言----深入理解指针(3)(二)https://developer.aliyun.com/article/1544349