#include <stdio.h>
#include <limits.h>
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)
*/
}