指针与数组

时间:2022-07-24
本文章向大家介绍指针与数组,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
#include <stdio.h>
#include <limits.h>
void main1(){
 int a[5] ={1,2,3,4,5};
 // a=0x1233333; a是常量,不能为左值
 printf("%x,%d,%xn",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,%dn",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("nn");
 //指针比较
 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("%xn",p);   //61feb8
 printf("%d,%xn",*p++,p );  // 1,61febc   优先级 *p++  等价于*(p++)  ++的优先级比*大,即先引用p的值*p,后自增p++,即: *p, p=p+1,等于于 a[i++]
 // printf("%d,%xn",(*p)++,p );// 1,61feb8    先取*p,再引用1,后再+1, (*p)++=2,p没有变
 //printf("%d,%xn",*++p,p );//2,61febc 等价于 *(++p)  先自增++p,即&a[1],后引用*(p=p+1),等价于 a[++i]  = a[2]
 int *p1 =&a[1];
 int *p2 =&a[3];
 printf("%dn",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,%xn",a,&a);  //61feb4,61feb4  a和&a的地址一样,但是他们指向的类型不一样  在a和&a前面加*,即是他们所指向的类型
 //printf("%d,%dn", sizeof(a), sizeof(&a));  //20,4  a指向数组首地址,&a是a的地址,这个打印无意义,不用研究
 printf("%d,%dn", 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,%dn", sizeof(p), sizeof(pa));  //4,4       指针地址固定4个字节
 //printf("%d,%dn", sizeof(p), sizeof(&pa));  //4,4   指针地址固定4个字节
 printf("%d,%dn", 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,%pn",a,&a,*a); //打印三者的地址0061FEA0,0061FEA0,0061FEA0  地址一样
 printf("%d,%d,%dn", 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,%dn", 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)
*/
}