指针与数组
Posted luoxuw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了指针与数组相关的知识,希望对你有一定的参考价值。
#include <stdio.h> #include <limits.h> //操作数组的本质是操作指针,因为指针太麻烦,不便于理解,所以才抽象出简单的指针,也是就是数组,a[i]是 *(a+i)的简写 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void main1() int a[5] =1,2,3,4,5; // a=0x1233333; a是常量,不能为左值 printf("%x,%d,%x\n",a,*a,*(a+1)); //61feac,1,2 //数组名a代表数组的首地址,,*a就是按照int类型往后取出4个字节的数据,按照int类型来解析 %d来解析 //数组名a代表数组的首地址,a+1要按照a的类型给a地址加1,也就是加int类型的四个字节,a+1=&a[1] for (int i = 0; i < 5; ++i) printf("%x,%x",&a[i],a+i); //&a[i]等价于a+i,a+i就是从首地址a开始,每次往后移动i个sizeof(int)个字节数的地址 printf(" %d,%d\n",a[i],*(a+i)); // a[i]本质等价于 *(a+i) 然后再从上面的首地址读取int类型的数据 //用指针循环方式遍历数组,数组名是一个常量地址 a=a 是错误的,常量无法赋值 int *px =a; //a常量地址赋值给指针变量 for (; px < a+5 ; ++px) //指针每次自增,往前移动4个字节,也就是一个数组元素,指针自增不要越界,只有在数组内才有意义 printf("%d ",*px); //指针方式循环,px的值会改变 printf("\nfour ways of presenting array are the same:\n"); int *p =a; for (int i = 0; i < 5; ++i) printf("%d,%x ",a[i],&a[i]); printf("%d,%x ",*(a+i),a+i); printf("%d,%x ",p[i],&p[i]); //i的方式循环p的值不变 printf("%d,%x \n",*(p+i),p+i); /*four ways of presenting array are the same: 1,61fea4 1,61fea4 1,61fea4 1,61fea4 2,61fea8 2,61fea8 2,61fea8 2,61fea8 3,61feac 3,61feac 3,61feac 3,61feac 4,61feb0 4,61feb0 4,61feb0 4,61feb0 5,61feb4 5,61feb4 5,61feb4 5,61feb4 * */ printf("\n\n"); //指针比较 int num=SHRT_MAX +100; short *p1 =# double *p2 =# if(p1==p2) //指针可以比较地址,是否相等,地址相等并不意味着其所指向的值相等,还要看他们如何按其类型解析 printf("指针相等\n"); printf("%d!=%d",*p1,*p2); //-32669!=32867 // 优先级 *p++ 等价于*(p++) ++的优先级比*大,即先引用p的值*p,后自增p++,即: *p, p=p+1,等于于 a[i++] //*(++p) 先自增++p,后引用*(p=p+1),等价于 a[++i] // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void main2() int a[5] =1,2,3,4,5; int *p =a; printf("%x\n",p); //61feb8 printf("%d,%x\n",*p++,p ); // 1,61febc 优先级 *p++ 等价于*(p++) ++的优先级比*大,即先引用p的值*p,后自增p++,即: *p, p=p+1,等于于 a[i++] // printf("%d,%x\n",(*p)++,p );// 1,61feb8 先取*p,再引用1,后再+1, (*p)++=2,p没有变 //printf("%d,%x\n",*++p,p );//2,61febc 等价于 *(++p) 先自增++p,即&a[1],后引用*(p=p+1),等价于 a[++i] = a[2] int *p1 =&a[1]; int *p2 =&a[3]; printf("%d\n",p1-p2); // -2 p1-p2 <0 p1 < p2 p1的下标小于p2的下标 //指针相减多用于同一块内存,如数组或动态申请的内存,结果等于:地址差/sizeof(类型) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void main3() int *pInt; double *pDouble; printf("%d,%d,%d,%d", sizeof(*pInt), sizeof(*pDouble),sizeof(pInt), sizeof(pDouble)); //4,8,4,4 //sizeof(*pInt), sizeof(*pDouble),sizeof(pInt), sizeof(pDouble) // 4 8 4 4 // *pInt *pDouble pInt pDouble // int类型数据 double类型数据 int类型指针 double类型指针,指针大小固定为4个字节 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //指向数组的指针和指向元素的指针 ???? void main4() int a[5] =1,2,3,4,5; printf("%x,%x\n",a,&a); //61feb4,61feb4 a和&a的地址一样,但是他们指向的类型不一样 在a和&a前面加*,即是他们所指向的类型 //printf("%d,%d\n", sizeof(a), sizeof(&a)); //20,4 a指向数组首地址,&a是a的地址,这个打印无意义,不用研究 printf("%d,%d\n", sizeof(*a), sizeof(*(&a))); //4,20 *a是a指向数组的第一个元素,占4个字节,*(&a)是&a指向整个数组,是20个字节 int *p = a; //指向元素的指针 a=&a[0] int (*pa)[5] = &a; //指向有5个元素数组的指针. // 括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int [4],这正是 a 所包含的每个一维数组的类型。 // [ ]的优先级高于*,( )是必须要加的,如果赤裸裸地写作int *p[4],那么应该理解为int *(p[4]),p 就成了一个指针数组,而不是二维数组指针 //printf("%d,%d\n", sizeof(p), sizeof(pa)); //4,4 指针地址固定4个字节 //printf("%d,%d\n", sizeof(p), sizeof(&pa)); //4,4 指针地址固定4个字节 printf("%d,%d\n", sizeof(*p), sizeof(*pa)); //4,20 *p指向元素, *pa指向数组 //*(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址, // 因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字, // 在定义时或者和 sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //指针引用多为数组 void main() int a[3][4]=1,2,3,4, 5,6,7,8, 9,11,12; printf("%p,%p,%p\n",a,&a,*a); //打印三者的地址0061FEA0,0061FEA0,0061FEA0 地址一样 printf("%d,%d,%d\n", sizeof(*a), sizeof(*&a), sizeof(**a)); //打印三者所指向的类型大小 16,48,4 // a指向二维数组的行元素大小的指针 16 =4 *4 // &a指向二维数组大小的指针 48 = 12 *4 // a指向二维数组的单个元素大小的指针 4 //打印二维数组 for (int i = 0; i < 3; ++i) for (int j = 0; j < 4; ++j) printf("%d %p, ",a[i][j],&a[i][j]); printf("\n"); printf("%d,%d\n", sizeof(*a), sizeof(**a)); //16 4 a是行指针 *a是列指针 *a=*(a+0)=a[0] a[i]是一个列指针,&a[i]代表行指针 printf("%p,%p,%p \n",a,a+1,a+2); //a,a+1,a+2分别代表二维数组第一,二,三行的首地址,a是行指针 printf("%p,%p,%p \n",*a,*a+1,*a+2); //*a,*a+1,*a+2分别代表二维数组第一行第一、二、三列元素的地址 *a是第一行首列指针 *取列 printf("%p,%p,%p \n",*(a+1),*(a+1)+1,*(a+2)); printf("%p,%p,%p \n",a[1],a[1]+1,a[3]); //*(a+1),*(a+1)+1 分别指向第二行第一列和第二行第二列元素的指针 <=> a[1] //*(a+2) 指向第三行第一列元素的指针 <=> a[3] // a[i]是一个列指针,第i行第一列的地址;&a[i]代表行指针,第i行的首地址 //结论: a[i][j] = *(*(a+i)+j) &a[i][j] = *(a+i)+j /* &a[i]== a+i == p+i &a[i]代表行指针,第i行的首地址 a[i] == p[i] == *(a+i) == *(p+i) a[i]是一个列指针,第i行第一列的地址; &a[i][j] == &p[i][j] == a[i]+j == p[i]+j == *(a+i)+j == *(p+i)+j a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j) */
以上是关于指针与数组的主要内容,如果未能解决你的问题,请参考以下文章