在前面講解完畢指標相關內容后,下面便開始進行答題模擬
再進行做題以前,我建議自己先行快速瀏覽一下指標內容:
指標基礎
指標進階
文章目錄
- 在前面講解完畢指標相關內容后,下面便開始進行答題模擬
- 陣列筆試題講解
- 一維陣列
- 整型陣列
- 字符陣列
- `sizeof求字符大括號陣列`
- `strlen求字符陣列標準寫法`
- `sizeof求取標準寫法陣列`
- `strlen求取標準字串`
- 常量字符指標
- 關于`strlen`求常量字串長度
- 二維陣列
- 總結 :陣列名的意義:
- 指標筆試題講解
- 筆試題1
- 筆試題2
- 筆試題3
- 筆試題4
- 筆試題5
- 筆試題6
- 筆試題7
- 筆試題8
陣列筆試題講解
一維陣列
整型陣列
請問下面的答案依次是什么???
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));// 1
printf("%d\n",sizeof(a+0));// 2
printf("%d\n",sizeof(*a));// 3
printf("%d\n",sizeof(a+1));// 4
printf("%d\n",sizeof(a[1]));// 5
printf("%d\n",sizeof(&a));// 6
printf("%d\n",sizeof(*&a));// 7
printf("%d\n",sizeof(&a+1));// 8
printf("%d\n",sizeof(&a[0]));// 9
printf("%d\n",sizeof(&a[0]+1));//10
/*
1. 16
2. 4 or 8
3. 4
4. 4 or 8
5. 4
6. 4 or 8
7. 16
8. 4 or 8
9. 4 or 8
10.4 or 8
*/
決議:
- 當只有陣列名和sizeof結合時候,表示求整個陣列大小. 所以結果是 4 * 4 = 16
- a+0是一個運算式,sizeof(a+0)就認為a是地址,0是地址,地址加地址還是地址,地址(指標)的大小只能是4或者8
- *a是陣列a第一個元素,是一個整型,整型的大小是4個位元組,所以結果是 4
- a+1和第二個一樣,測的地址,地址(指標)大小只能是4或者8
- a[1]是一個整數,同理,整型大小是4個位元組
- &a是一個地址,同理只能是4或者8
- *&a中
*與&是互相抵消的,所以*&a等于a,而只有陣列名和sizeof結合時,就代表求整個陣列大小,所以是4 * 4=16- 9.10都是地址相加減,所以只能是4或者8
字符陣列
sizeof求字符大括號陣列
下面會出現三組題,有一定的坑洞;
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));// 1
printf("%d\n", sizeof(arr+0));// 2
printf("%d\n", sizeof(*arr));// 3
printf("%d\n", sizeof(arr[1]));// 4
printf("%d\n", sizeof(&arr));// 5
printf("%d\n", sizeof(&arr+1));// 6
printf("%d\n", sizeof(&arr[0]+1));// 7
/*
答案:
1. 6
2. 4 or 8
3. 1
4. 1
5. 4 or 8
6. 4 or 8
7. 4 or 8
*/
決議:
當陣列名與
sizeof結合時候,表示求整個陣列大小,所以arr陣列的大小是6;
sizeof中不是單獨的陣列名,所以arr+0這時候表示arr是一個地址,arr+0還是等于arr,一個地址的大小就是4 or 8
*arr表示首元素,而首元素是字符'a',一個字符的大小是一個位元組,所以答案是1;
arr[1]代表的是第二個元素,第二個元素是'b',所以一個字符的大小就是一個位元組,所以答案是1;
- 題目中 &arr表示的是陣列地址,所以后面無論怎么加減都是地址,地址的大小是4 or 8;
&arr[0] + 1還是一個地址,只是第二個元素的地址,而地址的大小是 4 or ;
strlen求字符陣列標準寫法
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", strlen(arr));// 1
printf("%d\n", strlen(arr+0));// 2
printf("%d\n", strlen(*arr));// 3
printf("%d\n", strlen(arr[1]));// 4
printf("%d\n", strlen(&arr));// 5
printf("%d\n", strlen(&arr+1));// 6
printf("%d\n", strlen(&arr[0]+1));// 7
/*
答案:
1. 隨機值
2. 隨機值
3. 報錯
4. 報錯
5. 隨機值
6. 在第一題的隨機值上減6
7. 在第一題的隨機值上減1
*/
決議:
注意: 這里是
strlen,不再是sizeof,strlen接收的引數是地址,并從該地址后面進行查找\0,直到找到為止
- arr是首元素地址,所以
strlen變開始從a進行往后找尋\0,但是arr陣列是沒有的\0的,所以他會越過陣列界限,直到找到為止,因此說最后回傳的是一個隨機值.
arr+0還是arr,因此照樣從
a開始往后面進行查詢,與第一天一樣,還是一個隨機值4.題都是傳送的一個字符,即傳送了一個整數(字符本質還是整數),但是要求傳送地址,所以報錯
&arr是陣列地址,但是&arr的值和 arr一模一樣,所以還是會回傳一個隨機值.
&arr+1,表示跨越整個陣列,最后指向陣列末尾,于是從
陣列末尾開始向后查找\0的值,因此回傳的隨機值是相比于第一題減去6
&arr[0]+1首元素地址加一,代表第二個元素地址,因此從此開始向后查詢\0,因此最后回傳的隨機值相比第一題減去1;下面是除去3.4.兩個報錯題其他題的結果:完全與決議溫吻合
sizeof求取標準寫法陣列
char arr[] = "abcdef"; printf("%d\n", sizeof(arr));// 1 printf("%d\n", sizeof(arr+0));// 2 printf("%d\n", sizeof(*arr));// 3 printf("%d\n", sizeof(arr[1]));// 4 printf("%d\n", sizeof(&arr));// 5 printf("%d\n", sizeof(&arr+1));// 6 printf("%d\n", sizeof(&arr[0]+1));// 7 /* 答案: 1. 7 2. 4 or 8 3. 1 4. 1 5. 4 or 8 6. 4 or 8 7. 4 or 8 */決議:
當只有陣列名與
sizeof結合時候,表示求得是整個陣列大小,所以整個陣列大小是 7(包括\0)
arr+0不是單獨的陣列名與sizeof結合在一起.所以arr是一個地址,地址的大小是 4 or 84.題目都是一個確定的字符,一個字符的大小是 1直位元組,所以答案是
1位元組6.7.都是求取的地址,地址的大小是 4 or 8;
strlen求取標準字串
char arr[] = "abcdef";
printf("%d\n", strlen(arr));//1
printf("%d\n", strlen(arr+0));//2
printf("%d\n", strlen(*arr));//3
printf("%d\n", strlen(arr[1]));//4
printf("%d\n", strlen(&arr));//5
printf("%d\n", strlen(&arr+1));//6
printf("%d\n", strlen(&arr[0]+1));//7
/*
答案:
1. 6
2. 6
3. 報錯
4. 報錯
5. 6
6. 隨機值
7. 5
*/
決議: strlen是接收地址并且往后查找\0,然后停止
arr是首元素地址,往后查找,可以找到\0,所以是 6
arr+0還是首元素地址,往后查找,可以找到\0,所以還是 64.之前我們講過的類似,他們傳的是整型(字符本質),不是地址,所以報錯
&arr是陣列地址,但是&arr與arr的值一樣,都是從第一個元素開始查找,所以答案還是6
&arr[0] + 1是第二個元素的地址,所以從他開始往后查找們就會少一個首元素,所以值 是 6-1 = 5下面還是除去報錯的3.4.題之外的結果:
常量字符指標
注意這里的區別,很多人會容易搞錯
char *p = "abcdef"; //這種寫法代表"abcdef"是常量字串,只給p存放了一個a的地址,且*p路不可修改
printf("%d\n", sizeof(p));// 1
printf("%d\n", sizeof(p+1));// 2
printf("%d\n", sizeof(*p));// 3
printf("%d\n", sizeof(p[0]));// 4
printf("%d\n", sizeof(&p));// 5
printf("%d\n", sizeof(&p+1));// 6
printf("%d\n", sizeof(&p[0]+1));// 7
/*
答案:
1. 4 or 8
2. 4 or 8
3. 1
4. 1
5. 4 or 8
6. 4 or 8
7. 4 or 8
*/
決議:
p是指標,即字符a的地址,所以在上面中除了 3 4小題之外,其余的所有運算式都是求取指標(地址)大小,所以指標大小只能是4 或者 8而2 3小題中
*p等于a,而p[0]等于*(p + 0)也是字符a(不明白這個關系的請看這里陣列名與地址關系) 所以3 4小題都是 1
關于strlen求常量字串長度
char* p = "abcdef"; //這種寫法代表"abcdef"是常量字串,只給p存放了一個a的地址;
printf("%d\n", strlen(p)); //1
printf("%d\n", strlen(p + 1));//2
printf("%d\n", strlen(*p));//3
printf("%d\n", strlen(p[0]));//4
printf("%d\n", strlen(&p));//5
printf("%d\n", strlen(&p + 1));//6
printf("%d\n", strlen(&p[0] + 1));//7
/*
答案:
1. 6
2. 5
3. error
4. error
5. 隨機值
6. 隨機值
7. 隨機值
*/
決議:
p是
a的地址,所以向a的地址后面查找\0,所以 答案是 6p+1是地址向后移動一位,然后從該地址處向后找
\0,所以答案是 54…這兩個題和之前的一樣,
strlen要求接收地址,但是*p與p[0]都是確切的數值,所以報錯5.6.7.題都是在 p的地址上操作,而p后面的地址所指向元素是否為0,不可知,所以都是隨機值.
二維陣列
這里要求對陣列名關系掌握準確,可以看這篇文章陣列名與地址
并且一個二維陣列是多個一維陣列串聯在一起的.
int a[3][4] = {0};
printf("%d\n",sizeof(a)); // 1
printf("%d\n",sizeof(a[0][0]));// 2
printf("%d\n",sizeof(a[0]));// 3
printf("%d\n",sizeof(a[0]+1));// 4
printf("%d\n",sizeof(*(a[0]+1)));// 5
printf("%d\n",sizeof(a+1));// 6
printf("%d\n",sizeof(*(a+1)));// 7
printf("%d\n",sizeof(&a[0]+1));// 8
printf("%d\n",sizeof(*(&a[0]+1)));// 9
printf("%d\n",sizeof(*a));// 10
/*
答案:
1. 48
2. 4
3. 16
4. 4 or 8
5. 4
6. 4 or 8
7. 16
8. 4 or 8
9. 16
10.16
*/
決議:
- a是陣列名,單獨與
sizeof在一起表示求整個陣列大小,所以大小是3*4*4=48a[0][0]是一個確切的數字,即第一行第一列的數字,整型的大小是4個位元組- a[0]代表的是第一行陣列的陣列名,而陣列名單獨與
sizeof在一起表示求的是整個陣列的大小,所以大小是4 * 4 = 16- a[0]是第一行陣列名,即地址,地址加1還是地址,所以地址的大小是
4 or 8a[0] + 1代表第一行第二列的元素地址,前面有*,所以是求第一行第二列元素的大小,所以是 4個位元組- a是地址,a+1還是地址,地址的大小是
4 or 8- a是
首元素地址,即第一行的陣列地址,a+1代表是第二行的陣列地址,前面有個*,所以*(a+1)是第二行的陣列名,陣列名單獨與sizeof在一起表示求的是整個陣列大小,所以第二行的陣列大小是4 * 4 = 16- &a[0]是地址,地址加一還是地址,地址的大小是
4 or 8&a[0]+1代表第二行的陣列地址,前面有個*,則變成了第二行的陣列名 ,陣列名單獨與sizeof結合在一起,表示整個陣列大小,所以第二行的陣列大小是4 * 4 = 16- a是第一行陣列地址,前面有個
*,表示第一行陣列的陣列名,陣列名單獨與sizeof結合在一起.所以大小是4 * 4 = 16下面是32位與64位機器下的運行結果:
總結 :陣列名的意義:
sizeof(陣列名),這里的陣列名表示整個陣列,計算的是整個陣列的大小,&陣列名,這里的陣列名表示整個陣列,取出的是整個陣列的地址,
除此之外所有的陣列名都表示首元素的地址,
指標筆試題講解
在講解下面的例子時候,我強烈建議大家先看看 陣列名與地址關系文章
筆試題1
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int *)(&a + 1);
printf( "%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
/*
結果:
2 5
*/
決議:
&a是陣列地址,&a+1是指標指向陣列a末尾,前面有一個強制性整型指標轉換,此時的ptr則指向陣列末尾,且是一個整型指標所以
ptr-1就是5的地址,所以解參考就是 5
a是陣列第一個元素地址,加1,就是第二個元素地址,解參考就是 2下面是圖解
筆試題2
//由于還沒學習結構體,這里告知結構體的大小是20個位元組
//假設p 的值為0x100000, 如下表運算式的值分別為多少?
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
int main()
{
p = 0x00100000;
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
/*
答案:
0x00100014
0x00100001
0x00100004
*/
決議:
p是結構體指標,可以跨越20個位元組,所以
p+1就是地址跨越20個,所以在0x00100000上增加0x00000014(16進制的20),所以答案是
0x00100014p是結構體指標,但是前面有強制性無符號整型型別轉化,所以把p變成了一個長整型,即一個**數字,**那么數字加一,就是在
0x00100000上加0x00000001,所以結果是0x00100001p是結構體指標,但是前面有強制性無符號整型指標型別轉化,所以p是一個整型指標,所以整型指標加1,地址跳躍4個位元組,所以在原來的基礎上加
0x00000004;, 所以結果是0x00100004
筆試題3
int main()
{
int a[5] = { 1, 2, 3, 4 ,5};
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
printf( "%x,%x", ptr1[-1], *ptr2);
return 0;
}
/*答案:
0x00000005
0x02000000
*/
決議:
&a+1是陣列地址加一,則指向了陣列末尾,然后前面有強制整型指標型別轉換,所以此時ptr1是整型指標,且指向陣列的末尾又因為
ptr1[-1]等于*(ptr1 -1 ),代表指標位置向前移動一位,即指向4,所以答案是0x00000004a是陣列的首元素1的地址,前面又強制型別轉換為整數,然后在整數的基礎上加一,最后再換成整型指標,我們以圖說明

*可以看到經過小端存盤以后,隨著地址的變化,就可以知道值,第二問中 (int )((int)a + 1)指向了00解參考即向后訪問4個位元組
即得到 00 00 00 02,由于這是小端存盤,所以真正的數字是 02 00 00 00
筆試題4
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf( "%d", p[0]);
return 0;
}
/*
答案:
1
*/
決議:
(0,1)這種是逗號運算式,所以真正存進陣列a的是
1 ,3 ,5由于這是一個二維陣列,所以a[0]是第一行的陣列名,即第一行第一列的元素的地址.
所以
p[0]等價于*(a[0] + 0)即第一行第一列的元素 所以答案是 1
筆試題5
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
10000000 00000000 00000000 00000100
11111111 11111111 11111111 11111011
1111 1111 1111 1111 1111 1111 1111 1100
FFFFFFFC
/*
答案:
FFFFFFFC,-4
*/

決議:
由圖中所畫可以知道
&p[4][2] - &a[4][2]的結果是-4(地址相減代表中間元素個數)-4的補碼是
11111111 11111111 11111111 11111100因此上式化成
%p形式是FFFFFFFC? 化成
%d形式是-4
筆試題6
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));
return 0;
}
/*
答案:
10 , 5
*/
決議:
首先這是一個二維陣列.
- 所以
&aa+1代表跨越整個二維陣列.即指向10的末尾.然后前面強制型別轉換為int*,所以ptr1此時是整型指標.指向10的末尾.? 所以
*(ptr1 - 1)就是10
aa是第一行的陣列地址,aa+1就是5的末尾.*(aa+1)即是第二行的陣列名,即元素6的地址前面又強制型別轉換為int*,所以此時ptr2是整型指標.*(ptr-1)就是 5
筆試題7
#include <stdio.h>
int main()
{
char* a[] = {"work","at","alibaba"};
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
/*
答案:
at
*/
![]()
由此可以看出,pa++以后指向了陣列a的第二塊空間,
*pa即得到了a的地址,因此列印出來就是at
筆試題8
int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp+3);
printf("%s\n", *cpp[-2]+3);
printf("%s\n", cpp[-1][-1]+1);
return 0; }
/*
答案:
POINT
ER
ST
EW
*/
![]()
- 同理,
char** * cpp代表cpp可以跳過char**大小,因此++cpp,即指向了陣列cp[1]的位置,第一次解參考,即得到c+2,而c+2則是指向陣列c[2],所以第二次解參考,即得到c[2]里面的內容(p的地址),所以列印就是POINT注意:第一題以后,
cpp的值就是加1過后了,即指向cp[1].所以第二題注意細節
*++cpp就如上一題說的一樣,即得到c+1(因為cpp已經在第一題加了一次),然而c+1前面有個--,所以c+1變成了c,而c指向的是陣列c[0],所以再次解參考就得到了c[0]里面的內容(E的地址),然而,E卻加3,即得到第二個E的地址,所以列印出來就是ER注意:同理注意經過兩次變化的
cpp的值.
- 因為
cpp[-2]等價于*(cpp-2)所以cpp-2便指向了cp[0],所以cpp[-2]的內容便是c+3, 然后*cpp[-2]就是解參考c+3,而c+3指向的是c[3]位置,解參考因此得到了F的地址,而F又加3,所以得到了S地址,所以最后列印STcpp[-1][-1]相當于*(*(cpp-1) -1),而cpp-1指向的是cp[1]位置,解參考的到時c+2然后c+2又減1.所以得到c+1,又因為c+1指向的是c[1]位置,所以*(c+1)便得到N的地址,而N又加一,所以得到E的地址,所以列印EW
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/279859.html
標籤:其他
上一篇:力扣 -- 設計回圈佇列(題解)
下一篇:Redis學習筆記




