指標與陣列筆試題決議
一維陣列
int main()
{
int a[]={1,2,3,4};
printf("%d\n",sizeof(a));//16
printf("%d\n",sizeof(a+0));//16(第一次的答案) -4 陣列名這里表示首元素地址,a+0還是首元素地址
printf("%d\n",sizeof(*a));//4
printf("%d\n",sizeof(a+1));//4
printf("%d\n",sizeof(a[1]));//4
printf("%d\n",sizeof(&a));//16 -4 &a取出的是陣列的地址,但是陣列的地址也是地址,答案4
printf("%d\n",sizeof(*&a));//4 -16 &a是陣列的地址,陣列的地址解參考訪問的陣列,sizeof計算就是陣列的大小
printf("%d\n",sizeof(&a+1));//1 -4 &a+1也是一個地址,跳過了一個陣列,
printf("%d\n",sizeof(&a[0]));//4
printf("%d\n",sizeof(&a[0]+1));//4
return 0;
}
字串
int main()
{
char arr[]={'a','b','c','d','e','f'};
printf("%d\n",sizeof(arr));//7 -6//sizeof計算的是陣列大小,6*1=6位元組
printf("%d\n",sizeof(arr+0));//1 -4//首元素地址
printf("%d\n",sizeof(*arr));//1
printf("%d\n",sizeof(arr[1]));//1
printf("%d\n",sizeof(&arr));//4
printf("%d\n",sizeof(&arr+1));//4
printf("%d\n",sizeof(&arr[0]+1));//4
printf("%d\n",strlen(arr));//6 //隨機值,stelen需要遇到\0才停止計數
printf("%d\n",strlen(arr+0));//1 //隨機值
//printf("%d\n",strlen(*arr));//err strlen(地址) *arr 首元素'a' a的ASCII的值為97,strlen就會將97作為地址,進行訪問,此時已經非法訪問了
//printf("%d\n",strlen(arr[1]));//err
//printf("%d\n",strlen(&arr));// 隨機值
//printf("%d\n",strlen(&arr+1));// 隨機值-6
printf("%d\n",strlen(&arr[0]+1));//1 //隨機值-1
return 0;
}
int main()
{
char arr[]="abcdef";
printf("%d\n",sizeof(arr));//6 -7 sizeof計算的陣列大小,單位是位元組:7
printf("%d\n",sizeof(arr+0));//4 計算是地址的大小-arr,0是首元素地址
printf("%d\n",sizeof(*arr));//1 *arr是首元素,sizeof(*arr)計算首元素的大小
printf("%d\n",sizeof(arr[1]));//1 arr[1]是第二個元素,sizeof(arr[1])計算第二個元素的大小
printf("%d\n",sizeof(&arr));//4 &arr雖然是陣列的地址,但也是地址,大小是4/8位元組
printf("%d\n",sizeof(&arr+1));//4 &arr+1是跳過整個陣列的地址,但也是地址
printf("%d\n",sizeof(&arr[0]+1));//4 &arr[0]+1是第二個元素的地址
printf("%d\n",strlen(arr));//6
printf("%d\n",strlen(arr+0));//6
//printf("%d\n",strlen(*arr));//err
//printf("%d\n",strlen(arr[1]));//err
//printf("%d\n",strlen(&arr));//6 &arr 陣列的地址-陣列指標 char(*p)[7] =&arr; strlen的引數是const char*
//printf("%d\n",strlen(&arr+1));//隨機值
printf("%d\n",strlen(&arr[0]+1));//5
return 0;
}
int main()
{
char *p="abcdef";
printf("%d\n",sizeof(p));//4 計算指標變數的大小
printf("%d\n",sizeof(p+1));//4 p+1得到的字符b的地址
printf("%d\n",sizeof(*p));//1 *p就是字串的第一個字符--a
printf("%d\n",sizeof(p[0]));//1 p[0]==*(p+0) =='a'
printf("%d\n",sizeof(&p));//4 是取出p的地址,而不是計算陣列的大小
printf("%d\n",sizeof(&p+1));//4 取出跳過一個p的地址
printf("%d\n",sizeof(&p[0]+1));//4 取出b的地址
printf("%d\n",strlen(p));//6
printf("%d\n",strlen(p+1));//5
printf("%d\n",strlen(*p));//err
printf("%d\n",strlen(p[0]));//err
printf("%d\n",strlen(&p));//隨機值 取出的是p的地址,p后面\0位置不可知
printf("%d\n",strlen(&p+1));//隨機值
printf("%d\n",strlen(&p[0]+1));//5 取出的b的地址
二維陣列
int main()
{
int a[3][4]={0};
printf("%d\n",sizeof(a));//48
printf("%d\n",sizeof(a[0][0]));//4
printf("%d\n",sizeof(a[0]));//16
printf("%d\n",sizeof(a[0]+1));//16 -4 a[0]是第一行陣列名,陣列名此時代表的是首元素地址,a[0]+1 是第二個元素地址
printf("%d\n",sizeof(*(a[0]+1)));//4
printf("%d\n",sizeof(a+1));//4 a是二維陣列的陣列名,沒有sizeof(陣列名),也沒有&(陣列名),所以a是首元素地址,而把二維陣列看成一維陣列時,二維陣列的首元素就是它的第一行,a就是第一行地址,a+1就是第二行地址
printf("%d\n",sizeof(*(a+1)));//4 -16 *(a+1)就是對第二行解參考
printf("%d\n",sizeof(&a[0]+1));//4
printf("%d\n",sizeof(*(&a[0]+1)));//4 -16 &(陣列名)代表是第一行陣列的地址,&a[0]+1就是第二行地址,對其解參考就是對第二行解參考
printf("%d\n",sizeof(*a));//4 -16 a是首元素地址-第一行地址,*a就是第一行
printf("%d\n",sizeof(a[3]));//16
return 0;
}
看代碼說結果:
int main()
{
int a[5] = {1,2,3,4,5};
int *ptr = (int*)(&a+1);
printf("%d,%d", *(a+1),*(ptr-1));//2,5
return 0;
}
*(a+1),a是陣列名,代表的是首元素的地址,a+1就是第二個元素的地址, * (a+1)就是第二個元素,
&a+1 ,&a是取出整個陣列的地址,&a+1就是跳過一個陣列,指向陣列的后一個位置,ptr-1就是指向了陣列最后一個元素,解參考得到了陣列最后一個元素5
(因為a是陣列,a的地址型別是char * 所以需要強制型別轉化為 int * 才可以存盤到ptr中,)
第二題
//假設p的值為0x100000,如下運算式的值分別為多少?
//已知結構體Test型別的變數大小為20個位元組
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
int main()
{
printf("%p\n",p + 0x1);//0x100014 p是結構體指標,p+0x1 就是p+1,所以就是跳過一個結構體變數大小,就是跳過20個位元組,十六進制就是0x100014
printf("%p\n",(unsigned long)p + 0x1);//0x100001 p的型別強制轉化為(ungined long),p+1就是加上1,
printf("%p\n",(unsigned int*)p + 0x1);//0x100004 p的型別強制轉化為(ungined int*),p+1就是跳過一個指標,大小是4
return 0;
}
第三題
int main()
{
int a[4] = {1,2,3,4};
int *ptr1 = (int*)(&a+1);//
int *ptr2 = (int*)((int)a+1);//a作為陣列名,在這個代表首元素地址,強制轉化為int型別,a+1就是往后加一個位元組陣列內每一個元素都是4個位元組,向后加一個位元組,00 00 00 02 又因為記憶體是小端存盤,所以以16進制列印,就為0x02000000
printf("%x,%x",ptr1[-1],*ptr2);//4 , 200000
return 0;
}
第四題
int main()
{
int a[3][2] = {(0,1),(2,3),(4,5)};//!!!!注意陣列內是(0,1)(2,3)(4,5)這是逗號運算式,逗號運算式的結果是最后一個運算式的結果,所以二維陣列存的其實是 1 3 5 0 0 0
int *p;
p =a[0];//p拿到的是a[0] 也就是陣列第一行的地址
printf("%d",p[0]);//1 p[0]就是第一行第一個元素
return 0;
}
第五題
int main()
{
int a[5][5];
int(*p)[4];
p = a;// p的型別為int(*)[4] a的型別為 int(*)[5] a強制賦值給p,p指向第一行第一個元素 &p[4][2]就是 *((*(p+4))+2) 地址相減就是中間元素的個數,又因為是低地址減去高地址,所以得出的結果是負數
printf("%p,%d\n",&p[4][2]-&a[4][2],&p[4][2]-&a[4][2]);// FFFFFFFC , -4
//-4的原碼: 10000000000000000000000000000100
// 反碼:11111111111111111111111111111011
// 補碼: 1111 1111 1111 1111 1111 1111 1111 1100
// f f f f f f f c
return 0;
}

第六題
int main()
{
int aa[2][5] = {1,2,3,4,5,6,7,8,9,10};
int *ptr1 =(int*)(&aa+1);
int *ptr2 = (int*)(*(aa+1));
printf("%d,%d",*(ptr1-1),*(ptr2 -1));// 10,5
//&aa+1 跳過了一整個二維陣列,ptr1-1 就指向了10
// *(aa+1) ,aa+1相當于aa[1],ptr2指向了6的地址,ptr2-1就指向5
return 0;
}
第七題
int main()
{
char *a[]={"work","at","alibaba"};
char **pa = a;
pa++;
printf("&s\n",*pa);//"at"
return 0;
}

最復雜的一道題
int main()
{
char *c[] = {"ENTER", "NEW", "POINT", "FIRST"};
char **cp[] = {c+3, c+2, c+1, c};
char ***cpp = cp;
printf("%s\n",**++cpp);//POINT
printf("%s\n",*--*++cpp + 3);//ER
printf("%s\n", *cpp[-2] + 3);//ST
printf("%s\n", cpp[-1][-1]+1);//EW
return 0;
}

注意的一點是 ++cpp 時cpp的值已經加了1,在后續的計算中 不能使用cpp的原始值,而應該是運算后的值,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/282311.html
標籤:其他
