比較分析與數組相關的sizeof和strlen

// 形如:
int a[]={1,2,3,4,5};
char name[]="abcdef";

無論是整型數組還是字符數組,數組名作爲右值的時候都代表數組首元素的首地址。


數組發生降級數組名退化爲數組首元素的地址的情況:數組傳參、數組名參與運算

數組名不會發生降級的情況:sizeof(數組名)、取地址數組名(取到的是整個數組的地址而不是首元素的地址)


(以下結果都經過VS2013驗證)

我們先來定義兩個整型數組:

int a[] = { 1, 2, 3, 4 };
int p[5] = { 1, 2, 3, 4 };
printf("%d\n", p[4]);
printf("%d\n", sizeof(p));        //20
printf("%d\n", sizeof(a));        //16

數組a未定義數組的大小,sizeof(a)的結果是16;數組p定義了數組的大小,sizeof(p)的結果是20,系統會默認將p[4]初始化爲0;不論是a還是p,都求的是整個數組的大小

sizeof(a)其中有四個整型,一個整型4個字節,4*4=16個字節

int a[] = { 1, 2, 3, 4 };
printf("%d\n", sizeof(a + 0));    //4

因爲數組名a參與運算髮生了降級,變爲首元素的地址,a+0依舊是首元素的地址,相當於求sizeof(&a[0]) ,而一個地址本身是四個字節

int a[] = { 1, 2, 3, 4 };
printf("%d\n", sizeof(*a));     //4    對首元素的地址進行解引用取到首元素的值,爲int型
printf("%d\n", sizeof(a + 1));  //4    sizeof(&a[1])
printf("%d\n", sizeof(a[1]));   //4    數組的每個元素都是整型
printf("%d\n", sizeof(&a));     //4 取到整個數組的地址(地址爲四個字節存儲)
printf("%d\n", sizeof(&a + 1));         //4    地址的大小爲四個字節
printf("%d\n", sizeof(&a[0]));          //4    地址的大小爲四個字節
printf("%d\n", sizeof(&a[0] + 1));      //4    地址的大小爲四個字節
printf("%d\n", sizeof(*&a));          //16   &a取到整個數組的地址,再解引用取到整個數組

 sizeof(&a)在高版本的編譯器下結果都爲4,在低版本如VC6.0中爲16(這或許是VC6.0的一個BUG)


分析了int型數組的情況,我們再來看看char型數組的情況:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

char name1[10];         //定義全局性數組 系統默認初始化爲'\0'
int main()
{
           char name[10];
           printf("%d\n" , sizeof(name));    // 10
           printf("%d\n" , strlen(name));     // 隨機值

           printf("%d\n" , sizeof(name1));    // 10
           printf("%d\n" , strlen(name1));     // 0        
           system("pause" );
           return 0;
}

定義在全局的數組,及時你沒有初始化,系統也會默認初始化爲0,而name1在這裏是char類型,所以編譯器會自動把它初始化爲"\0".

sizeof(name)依舊算的是數組的大小,而strlen是遇到"\0"就結束

由於name沒有初始化,strlen(name)的結果是個隨機值,什麼時候遇到"\0",就什麼時候停下來。 

//***********************************************************************************//

char name[] = "abcdef" ;             // 6個字符還有一個"\0"
printf("%d\n" , sizeof(name[0]));    // 1  name[0]='a'  char一個字節存儲
printf("%d\n" , sizeof(&name));      // 4  取到整個數組的地址  地址爲四字節存儲
printf("%d\n" , sizeof(*name));      // 1   
printf("%d\n" , sizeof(&name + 1));  // 4  地址! (把整個數組都跳過去了)
printf("%d\n" , sizeof(name + 1));   // 4  數組名參與運算降級爲地址 ==> sizeof(&a[1])
printf("%d\n" , sizeof(name));       // 10    數組的大小
printf("%d\n" , strlen(name));       // 6     遇到'\0'就結束
printf("%d\n" , strlen(&name));      // 6   
//printf("%d\n", strlen(*name));     // 無效
printf("%d\n" , strlen(&name + 1));  // 隨機值 
printf("%d\n" , strlen(name + 1));   // 5  爲跳過首元素後的"bcdef"的長度

//***********************************************************************************//

strlen(&name) :strlen函數一個字符一個字符跳轉,直到遇到'\0'才結束。 這裏編譯器進行隱式的強制類型轉換成char*,相當於在求strlen(name)

strlen(&name + 1):這是一個隨機值,因爲&name + 1把整個數組都跳過去了,傳給strlen的參數是name數組後面未可知的地址,strlen會一直走下去,直到遇到"\0"

sizeof(*name):name發生降級,變爲首元素的首地址,再解引用取到字符'a'(*name='a'),輸出1


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章