首先,我們要清楚sizeof是C/C++中的一個操作符,其作用就是返回一個對象或者類型所占的內存字節數。
而,strlen是一個函數,函數原型為:
size_t strlen(const char *string);
strlen函數的作用是:計算給定字符串的長度,不包括'\0'在內
// 數組形如: 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)); // 無效,不能strlen字符 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
2016-04-12 16:24:56