歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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

首先,我們要清楚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

Copyright © Linux教程網 All Rights Reserved