C语言进阶——指针进阶(字符指针指针数组数组指针)

归志宁无五亩园,读书本意在元元。这篇文章主要讲述C语言进阶——指针进阶(字符指针指针数组数组指针)相关的知识,希望能为你提供帮助。
字符指针一般用法

//用字符指针存放字符 int main() { char ch = \'q\'; char * pc = & ch; *pc = \'w\'; return 0 ; }

还有一种用法
//用字符指针存放字符串 int main() { //本质上是把字符串"hello bit"的首字母h的地址放入*ps char* ps = "hello bit"; char arr[]="hello bit"; //验证指针*ps中存的是字符串首字母的地址 printf("%c\\n",*ps); //h//若要打印字符串"hello bit" printf("%s\\n",ps); printf("%s\\n",arr); return 0 ; }

int main() { char ch=\'w\'; //定义一个字符w char *p=& ch; //定义一个字符类型指针指向字符w / 或者说把字符w的存放地址存入字符类型指针p中 const char *p2="abcdef"; //定义一个字符类型指针p2存放字符串的首地址,也就是字符a的地址,只要找到a的地址就能对字符串进行操作 -- const修饰指针p指向的地址 return 0 ; }

一道面试题
int main() { char str1[]="hello bit."; //不同数组,地址不同 char str2[]="hello bit."; char* str3="hello bit."; //常量字符串,地址相同 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 为两个不同的数组,拥有不同的内存地址,而数组名存的是数组首元素的地址,所以不同 //str3 str4 为两个指针变量,里面都存了字符h的地址,字符串为常量字符串,是固定不可改的。hello bit只有一份,所以相同//《剑指offer》P49

指针数组
int main() { int arr[10]={0}; //整型数组 char ch[5]={0}; //字符数组int *parr[4]; //存放整型指针的数组 - 指针数组 //int * :数组的元素类型 //parr[4] :存放int* 类型元素的数组char *pch[5]; //存放字符指针的数组 - 指针数组return 0 ; }

PS
int (*parr3[10])[5]; //将数组名去掉 : int (* )[5]; - 类型 - 有五个元素的整型数组数组指针 //那么int (*parr3[10])[5]; 就是就是一个有10个元素大小的数组parr3- 存放着每个大小为五个元素的数组指针

int main() { //指针数组 //数组-数组中存放的是指针(地址) int* arr1[10]; //存放整型指针的数组 int a=10; int b=20; int c=30; int* arr3[3]={& a,& b,& c}; int i=0; for(i=0; i< 3; i++) { printf("%d ",*(arr[i])); }//指针数组 //指针数组里面放数组的首地址 int a[5]={1,2,3,4,5}; int b[]={2,3,4,5,6}; int c[]={3,4,5,6,7}; int* arr3[3]={a,b,c}; int i=0; //遍历打印数组内容 for(i=0; i< 3; i++) { int j=0; for(j=0; j< 5; j++) { printf("%d ",*(arr[i]+j)); //printf("%d",arr[i][j]); } printf("\\n"); }return 0 ; }

char* arr2[4]; //一级字符指针的数组 char** arr3[5]; //二级字符指针的数组

数组指针
  • 整型指针 - 指向整型的指针 - 可以存放整型的地址
  • pc是字符指针 - 指向字符的指针 - 可以存放字符的地址
  • 数组指针 - 指向数组的指针 - 存放数组的地址
int main() { int *p = NULL; //整型指针 - 指向整型的指针 - 可以存放整型的地址 char * pc = NULL; //pc是字符指针 - 指向字符的指针 - 可以存放字符的地址//数组指针 - 指向数组的指针 - 存放数组的地址 int arr[10] = {0}; //arr是首元素地址 //& arr[0] - 首元素的地址 //& arr - 数组的地址int arr[10]={1,2,3,4,5,6,7,8,9,10}; int(*p)[10]=& arr; //数组的地址要存起来 //& arr : 取数组arr的首地址 //p = & arr : 定义一个指针p存放arr的首地址 //int (*p)[10] = & arr : 定义一个整型数组指针*p存放数组,该指针大小为5个int元素大小//上面的p就是数组指针return 0; }

int main() { char* arr[5]; char* (*pa)[5] = & arr; int arr2[10]={0}; int (*pa2)[10]=& arr2; return 0 ; }

& arr arr
实际上:
  • 【C语言进阶——指针进阶(字符指针指针数组数组指针)】& arr表示的是数组的地址,而不是数组首元素的地址。
  • 数组的地址+1,跳过整个数组的大小,所以& arr+1相对于& arr的差值是40。
int main() { int arr[10] = {1,2,3,4,5,6,7,8,9,10}; int (*pa)[10]=& arr; int i=0; /* //1 for(i=0; i< 10; i++) { printf("%d ",(*pa)[i]); //*pa = arr } *//* //2 for(i=0; i< 10; i++) { printf("%d ",*(*pa+i)); //*pa = arr } *///3 int arr[10] = {1,2,3,4,5,6,7,8,9,10}; int *p=arr; int i=0; for(i=0; i< < 10; i++) { printf("%d ",*(p+i)); }return 0 ; }

//二维数组的使用 void print1(int arr[3][5],int x,int y) { int i=0; int j=0; for(i=0; i< x; i++) { for(j=0; j< y; j++) { printf("%d ",arr[i][j]); } printf("\\n"); } }//参数是指针的使用 void print2(int (*p)[5],int x,int y) { int i=0; for(i=0; i< x; i++) { int j=0; for(j=0; j< y; j++) { printf("%d ",*(*(p+i)+j)); printf("%d ",(*(p+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}}; //把二维数组看作一维数组时:第一行就是第一个元素,每一行是一个元素,那么数组名就是第一行的地址,print1(arr,3,5); //arr - 数组名 - 数组名就是首元素地址 print2(int *p[5],int x,int y); return 0 ; }//当用指针打印数组时的等价用法 int main() { int arr[10]={1,2,3,4,5,6,7,8,9,10}; int i=0; int* p=arr; for(i=0; i< 10; i++) { printf("%d ",p[i]); printf("%d ",*(p+i)); printf("%d ",*(arr+i)); printf("%d ",arr[i]); }return 0; }


    推荐阅读