前言
??
??在前面的學(xué)習(xí)中,我們已經(jīng)對C語言指針的知識(shí)有一個(gè)較為全面的了解,那么接下來我們做一些練習(xí)吧,即是檢驗(yàn)我們的學(xué)習(xí)成果,也是對之前的知識(shí)的鞏固。
??
??
一、 s i z e o f sizeof sizeof 與 s t r l e n strlen strlen 的對比
1.1、 s i z e o f sizeof sizeof
??
??因?yàn)楹竺娴牧?xí)題大量涉及
s
i
z
e
o
f
sizeof
sizeof 與
s
t
r
l
e
n
strlen
strlen ,這里我們將簡單回顧一下。
- s i z e o f sizeof sizeof 用于計(jì)算類型的大小,單位是字節(jié)。
- 括號(hào)中可以放置類型也可以放置表達(dá)式。他是一個(gè)操作符,而非函數(shù),當(dāng)后面放入的是表達(dá)式時(shí),括號(hào)可以省略不寫(這也側(cè)面驗(yàn)證了 s i z e o f sizeof sizeof 不是函數(shù),你見過函數(shù)行參考可以不帶括號(hào)的嗎)
- s i z e o f sizeof sizeof 只關(guān)心他里面的類型,表達(dá)式所占用空間的大小,并不進(jìn)行具體的計(jì)算。
舉例:
#include<stdio.h>
int main()
{
int a = 10;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof a);
printf("%d\n", sizeof(int));
return 0;
}
??
??
1.2、 s t r l e n strlen strlen
??
??
s
t
r
l
e
n
strlen
strlen 是C語言中的庫函數(shù),它用來計(jì)算字符串的長度。
??他的原理是從傳遞的指針變量開始,從前往后計(jì)算字符的個(gè)數(shù),知道遇到 ‘\0’ 停止( ‘\0’ 本身不計(jì)算)
??
??需要注意的是
s
t
r
l
e
n
strlen
strlen 是直到 ‘\0’ 才停止,一直沒有 ‘\0’ 則一直計(jì)算,因此
s
t
r
l
e
n
strlen
strlen 有可能會(huì)越界訪問
。
??
??
下面是
s
t
r
l
e
n
strlen
strlen 的 模擬實(shí)現(xiàn):
#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str)
{
assert(str);
const char* p = str;
while (*(str)++)
{
;
}
return str - p - 1;
}
??
??
s
t
r
l
e
n
strlen
strlen 的應(yīng)用舉例
#include<stdio.h>
int main()
{
char arr1[] = { 'a','b','c' };
char arr2[] = "abc";
printf("%d\n", strlen(arr1));
printf("%d\n", strlen(arr2));
printf("%d\n", sizeof(arr1));
printf("%d\n", sizeof(arr2));
return 0;
}
??文章來源地址http://www.zghlxwxcb.cn/news/detail-852405.html
1.3、 s i z e o f sizeof sizeof 和 s t r l e n strlen strlen 對比
??
s
i
z
e
o
f
sizeof
sizeof:
- s i z e o f sizeof sizeof 是
操作符
- s i z e o f sizeof sizeof 計(jì)算操作數(shù)所
占內(nèi)存空間的大小
,單位是字節(jié)
- s i z e o f sizeof sizeof
不關(guān)心
內(nèi)存中存放什么數(shù)據(jù)
??
s
t
r
l
e
n
strlen
strlen
- s t r l e n strlen strlen 是庫函數(shù),使用前需要包含頭文件 < s t r i n g . h > <string.h> <string.h>
- s t r l e n strlen strlen 是
求字符串長度
的,統(tǒng)計(jì)的是 ‘\0’ 之前字符的個(gè)數(shù)- s t r l e n strlen strlen 關(guān)注的是內(nèi)存中是否有 ‘\0’ ,如果不是 ‘\0’ 就會(huì)持續(xù)往后找,可能會(huì)
越界
。
??
??
二、數(shù)組和指針筆試題解析
??
2.1、題組一
int a[] = { 1,2,3,4,5 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));
printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));
??
??
答案:
20??4/8??4??4/8??4??4/8??20??4/8??4/8??4/8
??
-
printf("%d\n", sizeof(a));
數(shù)組名單獨(dú)放在 s i z e o f sizeof sizeof 中,這里的數(shù)組名代表整個(gè)數(shù)組,計(jì)算的是整個(gè)數(shù)組的大小。答案:20 -
printf("%d\n", sizeof(a + 0));
這里,雖然 s i z e o f sizeof sizeof(a)和 s i z e o f sizeof sizeof(a + 0)的計(jì)算結(jié)果是一樣的,但他們代表的含義并不一樣。 s i z e o f sizeof sizeof(a + 0)中,數(shù)組名 a a a 并沒有單獨(dú)放,此時(shí)的數(shù)組名表示數(shù)組首元素的地址,“+0” 地址不變,這里表示的是個(gè)指針變量,這個(gè)指針指向的是數(shù)組首元素。答案:4/8 -
printf("%d\n", sizeof(*a));
這里數(shù)組名表示的是數(shù)組首元素的地址,解引用為數(shù)組的元素,數(shù)組元素類型為 i n t int int。答案:4 -
printf("%d\n", sizeof(a + 1));
與上面的 s i z e o f ( a + 0 ) sizeof(a + 0) sizeof(a+0)一樣,都是指針變量,只是這里指向的是數(shù)組的第二個(gè)元素。答案:4/8 -
printf("%d\n", sizeof(a[1]));
這個(gè)很簡單,即數(shù)組第二個(gè)元素,類型為 i n t int int,等價(jià)于:*(a + 1) -
printf("%d\n", sizeof(&a));
指針變量,指向的是整個(gè)數(shù)組,可訪問 20 個(gè)字節(jié),雖然是數(shù)組指針,但只要是指針,大小就是4/8。答案:4/8 -
printf("%d\n", sizeof(*&a));
這里,& 和 ? * ? 互相抵消,即 ? * ? &a = a,即 s i z e o f ( a ) sizeof(a) sizeof(a)。答案:20 -
printf("%d\n", sizeof(&a + 1));
這里是指針變量,&a為指向整個(gè)數(shù)組,+1跳過了整個(gè)數(shù)組。該指針類型為 i n t int int(*)[ 5 ]。但這里不是野指針,因?yàn)? s i z e o f sizeof sizeof 是不會(huì)關(guān)心訪問里面的值的,你不能因?yàn)槲艺驹阢y行門口就說我搶銀行吧。答案:4/8 -
printf("%d\n", sizeof(&a[0]));
指針變量,指向數(shù)組首元素的指針,為 i n t ? int* int? 類型。答案:4/8 -
printf("%d\n", sizeof(&a[0] + 1));
指針變量,直向數(shù)組第二個(gè)元素的指針,只要是指針變量,為 i n t ? int* int? 類型。答案:4/8
??
??
??
2.2、題組二
char arr[] = { 'a','b','c','d','e','f' };
printf("%zd\n", sizeof(arr));
printf("%zd\n", sizeof(arr + 0));
printf("%zd\n", sizeof(*arr));
printf("%zd\n", sizeof(arr[1]));
printf("%zd\n", sizeof(&arr));
printf("%zd\n", sizeof(&arr + 1));
printf("%zd\n", sizeof( & arr[0] + 1));
??
??
答案:
6??4/8??1??1??4/8??4/8??4/8
??
-
printf("%zd\n", sizeof(arr));
數(shù)組名單獨(dú)放,表示整個(gè)數(shù)組。答案:6 -
printf("%zd\n", sizeof(arr + 0));
數(shù)組名沒有單獨(dú)放,后面有“+0”,表示的是指向首元素的指針,指針變量的大小為 4/8。這里不要因?yàn)? c h a r char char 類型大小為 1,所以就認(rèn)為 c h a r ? char* char? 大小也為 1,只要是指針類型它的大小就是 4/8。答案:4/8 -
printf("%zd\n", sizeof(*arr));
表示的是數(shù)組首元素,類型 c h a r char char。答案:1 -
printf("%zd\n", sizeof(arr[1]));
表示的是數(shù)組第二個(gè)元素,類型 char,等價(jià)于*(arr + 1)。答案:1 -
printf("%zd\n", sizeof(&arr));
表示的是指向整個(gè)數(shù)組的指針,指針變量的大小為 4/8,這里,不要以為他是數(shù)組類型的指針就以為他是 6,只要是指針類型,它的大小就是 4/8。答案:4/8 -
printf("%zd\n", sizeof(&arr + 1));
這題與上面一題類似,都是指針變量,+1跳過了整個(gè)數(shù)組(sizeof不會(huì)運(yùn)算里面的表達(dá)式,所以這里不算野指針)。答案:4/8 -
printf("%zd\n", sizeof( & arr[0] + 1));
字符指針,指向的是數(shù)組第二個(gè)元素。答案:4/8
??
??
??
2.3、題組三
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1))
??
??
答案:
隨機(jī)值??隨機(jī)值??程序無法運(yùn)行??程序無法運(yùn)行??隨機(jī)值??隨機(jī)值 - 6??隨機(jī)值 - 1
??
-
printf("%d\n", strlen(arr));
這里 a r r arr arr 表示的是首元素的地址, s t r l e n strlen strlen 函數(shù)從首元素開始,往后計(jì)數(shù),什么時(shí)候遇到 ‘\0’ 什么時(shí)候停下,計(jì)數(shù)停止。答案:隨機(jī)值 -
printf("%d\n", strlen(arr + 0));
這一題與上面的是一樣的。答案:隨機(jī)值 -
printf("%d\n", strlen(*arr));
這里,傳給 s t r l e n strlen strlen 函數(shù)的是數(shù)組首元素,即 ‘a(chǎn)’,字符 ‘a(chǎn)’ 的 ASCII值 為 97。因?yàn)? s t r l e n strlen strlen 函數(shù)接受的是指針類型的參數(shù),所以 s t r l e n strlen strlen 把 ‘a(chǎn)’ 當(dāng)做地址 0x00000097,該地址位于操作系統(tǒng)的內(nèi)核,無法訪問。答案:程序無法運(yùn)行 -
printf("%d\n", strlen(arr[1]));
這一題與上面一題同理,只是這里傳的是 ‘b’。答案:程序無法運(yùn)行 -
printf("%d\n", strlen(&arr));
& a r r arr arr 是指向整個(gè)數(shù)組的數(shù)組指針,雖然類型不同,但數(shù)值相同,分析方法與 s t r l e n ( a r r ) strlen(arr) strlen(arr)一樣。答案:隨機(jī)值 -
printf("%d\n", strlen(&arr + 1));
& a r r arr arr 為數(shù)組指針,加一跳過了整個(gè)數(shù)組,即跳過了 6 個(gè)字符,也是與上面一樣,直到遇到 ‘\0’ 才停止。答案:隨機(jī)值 - 6 -
printf("%d\n", strlen(&arr[0] + 1))
字符指針,指向首元素地址,+1 指向第二個(gè)元素,一直往后數(shù),直到 ‘\0’ 。答案:隨機(jī)值 - 1
??
??
??
2.4、題組四
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
??
??
答案:
7??4/8??1??1??4/8??4/8??4/8
??
-
printf("%d\n", sizeof(arr));
數(shù)組名單獨(dú)放,表示整個(gè)數(shù)組的大小,輸入的是字符串,后面還跟著 ‘\0’ 。答案:7 -
printf("%d\n", sizeof(arr + 0));
數(shù)組名不是單獨(dú)放,后面還有一個(gè)“+0”,為指向首元素地址的指針。答案:4/8 -
printf("%d\n", sizeof(*arr));
首元素地址解引用,表示數(shù)組首元素類型,類型為 c h a r char char 。答案:1 -
printf("%d\n", sizeof(arr[1]));
表示數(shù)組第二個(gè)元素,等價(jià)于 *(arr + i)。答案:1 -
printf("%d\n", sizeof(&arr));
數(shù)組指針,指向整個(gè)數(shù)組。答案:4/8 -
printf("%d\n", sizeof(&arr + 1));
數(shù)組指針,+1表 示跳過整個(gè)數(shù)組,但依然是數(shù)組指針類型。答案:4/8 -
printf("%d\n", sizeof(&arr[0] + 1));
字符指針,指向數(shù)組第二個(gè)元素。答案:4/8
??
??
??
2.5、題組五
char arr[] = "abcdef";
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1));
??
??
答案:
6??6??程序無法運(yùn)行??程序無法運(yùn)行??6??隨機(jī)值??5
??
-
printf("%d\n", strlen(arr));
正常傳址, s t r l e n strlen strlen 計(jì)算該字符串的大小。答案:6 -
printf("%d\n", strlen(arr + 0));
與上一題類似, s t r l e n strlen strlen 不會(huì)像 s i z e o f sizeof sizeof 那樣要區(qū)分?jǐn)?shù)組名是否單獨(dú)存放,對 s t r l e n strlen strlen 來說,數(shù)組名只有地址這一個(gè)選項(xiàng)。答案:6。 -
printf("%d\n", strlen(*arr));
這道題前面做過類似的,這里傳的是 ‘a(chǎn)’, s t r l e n strlen strlen 把‘a(chǎn)’(97)當(dāng)做地址,但該地址位于操作系統(tǒng)的內(nèi)核,用戶無法訪問。答案:程序無法運(yùn)行 -
printf("%d\n", strlen(arr[1]));
與上面一題類似。答案:程序無法運(yùn)行 -
printf("%d\n", strlen(&arr));
傳遞數(shù)組指針,但數(shù)值上等于數(shù)組首元素地址,從起始位置開始一個(gè)個(gè)往后計(jì)數(shù),直到一段遇到 ‘\0’ 停止。答案:6。 -
printf("%d\n", strlen(&arr + 1));
數(shù)組指針,+1 則跳過整個(gè)數(shù)組,從數(shù)組末尾開始計(jì)數(shù),什么時(shí)候遇到 ‘\0’ 什么時(shí)候停下。答案:隨機(jī)值 -
printf("%d\n", strlen(&arr[0] + 1));
字符指針,+1 跳過首元素,第二個(gè)元素開始往后計(jì)數(shù),直到遇到 ‘f‘ 后面的 ‘\0’。答案:5。
??
??
??
2.6、題組六
comst char* p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p + 1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p + 1));
printf("%d\n", sizeof(&p[0] + 1));
??
??
答案:
4/8??4/8??1??1??4/8??4/8??4/8
??
-
printf("%d\n", sizeof(p));
p p p 是字符指針,大小為 4/8 字節(jié),很簡單。答案:4/8 -
printf("%d\n", sizeof(p + 1));
與上面一樣,指針+1 還是指針。答案:4/8 -
printf("%d\n", sizeof(*p));
p p p 本質(zhì)是存放字符串首元素的地址,即 ‘a(chǎn)’ 的地址, p p p 解引用得到 ‘a(chǎn)’ ,為 c h a r char char 類型,大小為一個(gè)字節(jié)。答案:1 -
printf("%d\n", sizeof(p[0]));
這一句與上面的是一樣的。答案:1 -
printf("%d\n", sizeof(&p));
取出 p p p 的地址,為二級(jí)指針,本質(zhì)還是指針。答案:4/8 -
printf("%d\n", sizeof(&p + 1));
二級(jí)指針 +1,本質(zhì)還是指針變量。答案:4/8 -
printf("%d\n", sizeof(&p[0] + 1));
&p[0] + 1 == &*(p + 0) + 1,即 p + 1,還是指針變量。答案:4/8
??
??
??
2.7、題組七
char* p = "abcdef";
printf("%d\n", strlen(p));
printf("%d\n", strlen(p + 1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p + 1));
printf("%d\n", strlen(&p[0] + 1));
??
??
答案:
6??5??程序無法運(yùn)行??程序無法運(yùn)行??隨機(jī)值??隨機(jī)值??5
??
-
printf("%d\n", strlen(p));
正常傳址,正常計(jì)算字符串的大小。答案:6 -
printf("%d\n", strlen(p + 1));
從第二個(gè)字符開始計(jì)算字符串的大小。答案:5 -
printf("%d\n", strlen(*p));
*p就是‘a(chǎn)’-97。答案:程序無法運(yùn)行 -
printf("%d\n", strlen(p[0]));
p[ 0 ] = *(p + 0) = *p。答案:程序無法運(yùn)行 -
printf("%d\n", strlen(&p));
&p 取出的是 p 這個(gè)指針變量的地址,是二級(jí)指針,與字符串 “abcdef” 的關(guān)系就不大了。從 p 這個(gè)變量的地址開始往后數(shù),什么時(shí)候遇到 ‘\0’ 什么時(shí)候停,但這一切都是未知。答案:隨機(jī)值 -
printf("%d\n", strlen(&p + 1));
也是一樣的,+1 跳過了 4/8 的字節(jié),但是一切依然是未知的。答案:隨機(jī)值 -
printf("%d\n", strlen(&p[0] + 1));
&p[ 0 ]為取出首個(gè)字符的地址,+1即第二個(gè)字符的地址。答案:5
??
??
??
2.8、題組八
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0][0]));
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a[0] + 1));
printf("%d\n", sizeof(*(a[0] + 1)));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(*(a + 1)));
printf("%d\n", sizeof(&a[0] + 1));
printf("%d\n", sizeof(*(&a[0] + 1)));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a[3]));
??
??
答案:
48??4??16??4/8??4??4/8??16??4/8??16??16??16文章來源:http://www.zghlxwxcb.cn/news/detail-852405.html
??
-
printf("%d\n", sizeof(a));
數(shù)組名單獨(dú)放在 s i z e o f sizeof sizeof 中,表示整個(gè)數(shù)組的大小。答案:48 -
printf("%d\n", sizeof(a[0][0]));
表示的是數(shù)組第一行的首元素,類型為 i n t int int 。答案:4 -
printf("%d\n", sizeof(a[0]));
a[0] 可看成第一行這個(gè)一維數(shù)組的數(shù)組名,數(shù)組名單獨(dú)放在 s i z e o f sizeof sizeof 中,表示整個(gè)數(shù)組的大小。答案:16 -
printf("%d\n", sizeof(a[0] + 1));
第一行的數(shù)組名并沒有單獨(dú)放在 s i z e o f sizeof sizeof 中,因此這里的 a[0] 表示的是第一行首元素的地址,+1 則為第二個(gè)元素地址,但都是指針變量。答案:4/8 -
printf("%d\n", sizeof(*(a[0] + 1)));
a[0] + 1上面已經(jīng)分析過了,即第一行第二個(gè)元素,現(xiàn)在進(jìn)行解引用,為 i n t int int 類型。答案:4 -
printf("%d\n", sizeof(a + 1));
數(shù)組名不是單獨(dú)放置,這里的 a a a 表示的是數(shù)組首元素的地址,二維數(shù)組首元素為第一行,+1指向第二行的地址,但都是指針變量。答案:4/8 -
printf("%d\n", sizeof(*(a + 1)));
a + 1上面已經(jīng)分析過了,即第二行的地址,現(xiàn)在對其解引用,即整個(gè)第二行,類型為 i n t int int[ 3 ]。答案:16 -
printf("%d\n", sizeof(&a[0] + 1));
a[0] 為第一行數(shù)組的數(shù)組名,對其進(jìn)行 & 操作,取出的是整個(gè)第一行數(shù)組的地址,+1即指向第二行數(shù)組的指針。也可以這樣看 &a[0] + 1 = &(*(a + 0)) + 1 = & * a + 1 = a + 1,而 a + 1 前面已經(jīng)分析過了。答案:4/8 -
printf("%d\n", sizeof(*(&a[0] + 1)));
&a[0] + 1 上面剛剛分析過,為指向第二行數(shù)組的指針,對其進(jìn)行解引用,為第二行數(shù)組。答案:16 -
printf("%d\n", sizeof(*a));
這里 a a a 不是單獨(dú)放,代表首元素的地址,即第一行數(shù)組的地址,對其進(jìn)行解引用,得到第一行數(shù)組。答案:16 -
printf("%d\n", sizeof(a[3]));
a[3] 與 a[0] 是一樣的,因?yàn)? s i z e o f sizeof sizeof 并不會(huì)對里面的表達(dá)式進(jìn)行實(shí)際的勻運(yùn)算,所以并不算錯(cuò)。答案:16
到了這里,關(guān)于【C語言】——指針七:數(shù)組和指針試題解析的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!