C语言再学习 -- 关键字sizeof与strlen
sizeof?
一、簡單介紹
sizeof 是 C 語言的一種單目操作符,如 C 語言的其他操作符++、--等。它并不是函數(shù)。C 規(guī)定 sizeof 返回 sieze_t 類型的值。這是一個無符號整數(shù)類型。C99更進一步,把%zd 作為用來顯示 size_t 類型值的 printf() 說明符。如果你的系統(tǒng)沒有實現(xiàn) %zd,你可以試著使用 %u 或者 %lu 代替它。
sizeof 操作符以字節(jié)形式給出了其操作數(shù)的存儲大小。操作數(shù)可以是一個表達式或括在括號內(nèi)的類型名。操作數(shù)的存儲大小由操作數(shù)的類型決定。
二、使用方法
1、用于數(shù)據(jù)類型
sizeof 使用形式: sizeof (type)
數(shù)據(jù)類型必須用圓括號括住。如:sizeof (int)
2、用于變量
sizeof 使用形式:sizeof (var_name) 或 sizeof var_name
變量名可以不用圓括號括住。如:sizeof (6.08) 或 sizeof 6.08 等都是正確的形式。帶括號的用法更普遍,大多數(shù)程序員采用這種形式。
注意:sizeof 操作符不能用于函數(shù)類型,不完全類型和位字段。不完全類型指具有未知存儲大小的數(shù)據(jù)類型,如未知存儲大小的數(shù)組類型、未知內(nèi)容的結(jié)構(gòu)或聯(lián)合類型、void類型等。如:
sizeof (max) 若此時變量 max 定義為 int max ( ),
sizeof (char_v) 若此時 char_v 定義為 char char_v [MAX] 且 MAX 未知
sizeof (void)
上述例子,都是不正確的形式。
3、sizeof 的結(jié)果
sizeof 操作符的結(jié)果類型是 size_t,它在頭文件中 typedef 為 unsigned int 類型。該類型保證能容納實現(xiàn)所建立的最大對象的字節(jié)大小。
1)在windows,32位系統(tǒng)中
char ? ? ? ? 1個字節(jié)
short ? ? ? ?2個字節(jié)
int ? ? ? ? ? ?4個字節(jié)
long ? ? ? ? 4個字節(jié)
double ? ?8個字節(jié)
float ? ? ? ? 4個字節(jié)
看看這三個分別是什么?
1,‘ 1‘,“ 1”。
第一個是整形常數(shù), 32 位系統(tǒng)下占 4 個 byte;
第二個是字符常量,占 1 個 byte;
第三個是字符串常量,占 2 個 byte。
三者表示的意義完全不一樣,所占的內(nèi)存大小也不一樣,初學者往往弄錯。
2)當操作數(shù)為指針時,sizeof 依賴于編譯器。一般unix的指針為 4個字節(jié)
#include <stdio.h>int main (void) {char ptr[] = "hello";char *str = ptr;printf ("sizeof (str) = %d\n", sizeof (str));return 0; } 輸出結(jié)果: sizeof (str) = 4
在 32 位系統(tǒng)下,不管什么樣的指針類型,其大小都為 4 byte。可以測試一下 sizeof( void *)。
3)當操作數(shù)具有數(shù)組類型時,其結(jié)果是數(shù)組的總字節(jié)數(shù)
#include <stdio.h>int main (void) {int ptr[20] = {1,2,3,4,5};printf ("sizeof (ptr) = %d\n", sizeof (ptr));return 0; } 輸出結(jié)果: sizeof (ptr) = 80
4)聯(lián)合類型操作數(shù)的 sizeof 是其最大字節(jié)成員的字節(jié)數(shù),結(jié)構(gòu)體類型操作數(shù)的sizeof,需要考慮內(nèi)存對齊補齊。
參看:C語言再學習 -- 結(jié)構(gòu)和其他數(shù)據(jù)形式
[cpp]?view plaincopy
結(jié)構(gòu)體內(nèi)存對齊與補齊
一個存儲區(qū)的地址一定是它自身大小的整數(shù)倍(雙精度浮點類型的地址只需要4的整數(shù)倍就行了),這個規(guī)則也叫數(shù)據(jù)對齊,結(jié)構(gòu)體內(nèi)部的每個存儲區(qū)通常也需要遵守這個規(guī)則。數(shù)據(jù)對齊可能造成結(jié)構(gòu)體內(nèi)部存儲區(qū)之間有浪費的字節(jié)。結(jié)構(gòu)體的大小一定是內(nèi)部最大基本類型存儲區(qū)大小的整數(shù)倍,這個規(guī)則叫數(shù)據(jù)補齊。 [cpp]?view plaincopy
5)如果操作數(shù)是函數(shù)中的數(shù)組形參或函數(shù)類型的形參,sizeof給出其指針的大小
#include <stdio.h>char ca[10];void foo (char ca[100]) {printf ("sizeof (ca) = %d\n", sizeof (ca)); } int main (void) {char ca [25];foo (ca);return 0; } 輸出結(jié)果: sizeof (ca) = 4
三、主要用途
1、sizeof操作符的一個主要用途是與存儲分配和I/O系統(tǒng)那樣的例程進行通信。例如:void *malloc(size_t size), size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) ?
2、sizeof的另一個的主要用途是計算數(shù)組中元素的個數(shù)。例如:void *memset(void *s,int c,sizeof(s))
3.在動態(tài)分配一對象時,可以讓系統(tǒng)知道要分配多少內(nèi)存。如:int *p=(int *)malloc(sizeof(int)*10);
4.由于操作數(shù)的字節(jié)數(shù)在實現(xiàn)時可能出現(xiàn)變化,建議在涉及到操作數(shù)字節(jié)大小時用sizeof來代替常量計算。
5.如果操作數(shù)是函數(shù)中的數(shù)組形參或函數(shù)類型的形參,sizeof給出其指針的大小。
四、注意的地方
1、在混合類型的算術(shù)運算的情況下,較小的類型被轉(zhuǎn)換成較大的類型。反之,可能會丟失數(shù)據(jù)。
#include <stdio.h> #include <string.h> #include <stdlib.h>int main (void) {int a = 10;printf ("sizeof ((a > 5) ? 4 : 8.0) = %d\n", sizeof ((a > 5) ? 4 : 8.0));return 0; } 輸出結(jié)果: sizeof ((a > 5) ? 4 : 8.0) = 8
2、判斷表達式的長度并不需要對表達式進行求值
所以sizeof (b = a + 12)并沒有向 a 賦任何值。
strlen
strlen首先是一個函數(shù),只能以char * 做參數(shù),返回的是字符的實際長度,不是類型占內(nèi)存的大小。其結(jié)果是運行的時候才計算出來的。
#include <string.h>
size_t strlen(const char *s);
函數(shù)功能:用來統(tǒng)計字符串中有效字符的個數(shù)
功能實現(xiàn)函數(shù):
[cpp]?view plaincopy
strlen()函數(shù)被用作改變字符串長度,例如:
[cpp]?view plaincopy
可以看出:fit()函數(shù)在數(shù)組的第8個元素中放置了一個'\0'字符來代替原有的o字符。puts()函數(shù)輸出停在o字符處,忽略了數(shù)組的其他元素。然而,數(shù)組的其他元素仍然存在。
puts (str + 8);
表達式str + 8是str[8]即'r'字符的地址。因此puts()顯示這個字符并且繼續(xù)輸出知道遇到原字符串中的空字符。
sizeof 與 strlen 的區(qū)別
參看:C語言再學習 -- 字符串和字符串函數(shù)
談兩者的區(qū)別之前,先要講一下什么是字符串,字符串就是一串零個或多個字符,并且以一個位模式為全 0 的 '\0' 字節(jié)結(jié)尾。如在代碼中寫 "abc",那么編譯器幫你存儲的是 "abc\0"。
siezeof運算符提供給你的數(shù)目比strlen大1,這是因為它把用來標志字符串結(jié)束的不可見的空字符('\0')也計算在內(nèi)。
#include <stdio.h> #include <string.h> #include <stdlib.h>int main (void) {char *str1 = "abcde";char str2[] = "abcde";char str3[8] = "abcde";char str4[] = {'a', 'b', 'c', 'd', 'e'};char *p1 = malloc (20);printf ("sizeof (str1) = %d, strlen (str1) = %d\n", sizeof (str1), strlen (str1));printf ("sizeof (*str1) = %d, strlen (str1) = %d\n", sizeof (*str1), strlen (str1));printf ("sizeof (str2) = %d, strlen (str2) = %d\n", sizeof (str2), strlen (str2));printf ("sizeof (str3) = %d, strlen (str3) = %d\n", sizeof (str3), strlen (str3));printf ("sizeof (str4) = %d, strlen (str4) = %d\n", sizeof (str4), strlen (str4));printf ("sizeof (p1) = %d, sizeof (*p1) = %d\n", sizeof (p1), sizeof (*p1));printf ("sizeof (malloc(20)) = %d\n", sizeof (malloc (20)));return 0; } 輸出結(jié)果: sizeof (str1) = 4, strlen (str1) = 5 sizeof (*str1) = 1, strlen (str1) = 5 sizeof (str2) = 6, strlen (str2) = 5 sizeof (str3) = 8, strlen (str3) = 5 sizeof (str4) = 5, strlen (str4) = 5 sizeof (p1) = 4, sizeof (*p1) = 1 sizeof (malloc(20)) = 4總結(jié):
1. sizeof 操作符的結(jié)果類型是 size_t,它在頭文件中typedef為?unsigned int?類型。該類型保證能容納實現(xiàn)所建立的最大對象的字節(jié)大小。
2. sizeof 是算符,strlen 是函數(shù)。
3.?sizeof可以用類型做參數(shù),strlen只能用char*做參數(shù),且必須是以''\0''結(jié)尾的。sizeof 還可以用函數(shù)做參數(shù),比如:
short f();
printf("%d\n",sizeof(f()));
輸出的結(jié)果是sizeof(short),即2。
4.數(shù)組做 sizeof 的參數(shù)不退化,傳遞給 strlen 就退化為指針了。
5.大部分編譯程序 在編譯的時候就把 sizeof 計算過了 是類型或是變量的長度這就是 sizeof(x) 可以用來定義數(shù)組維數(shù)的原因
charstr[20]="0123456789";
int a=strlen(str);//a=10;
int b=sizeof(str);//而b=20;
6. strlen 的結(jié)果要在運行的時候才能計算出來,是用來計算字符串的長度,不是類型占內(nèi)存的大小。
7. sizeof 后如果是類型必須加括弧,如果是變量名可以不加括弧。這是因為sizeof是個操作符不是個函數(shù)。
8. 當適用了于一個結(jié)構(gòu)類型時或變量, sizeof 返回實際的大小,當適用一靜態(tài)地空間數(shù)組, sizeof 歸還全部數(shù)組的尺寸。sizeof 操作符不能返回動態(tài)地被分派了的數(shù)組或外部的數(shù)組的尺寸。
9.?數(shù)組作為參數(shù)傳給函數(shù)時傳的是指針而不是數(shù)組,傳遞的是數(shù)組的首地址,如:
fun(char [8])
fun(char [])
都等價于 fun(char *)
在C++里參數(shù)傳遞數(shù)組永遠都是傳遞指向數(shù)組首元素的指針,編譯器不知道數(shù)組的大小如果想在函數(shù)內(nèi)知道數(shù)組的大小, 需要這樣做:進入函數(shù)后用memcpy拷貝出來,長度由另一個形參傳進去
fun(unsiged char*p1, int len)
{
? ? unsigned char* buf= new unsigned char[len+1]
? ? memcpy(buf, p1,len);
}
我們能常在用到 sizeof 和 strlen 的時候,通常是計算字符串數(shù)組的長度看了上面的詳細解釋,發(fā)現(xiàn)兩者的使用還是有區(qū)別的,從這個例子可以看得很清楚:
charstr[20]="0123456789";
int a=strlen(str);//a=10; >>>> strlen 計算字符串的長度,以結(jié)束符 0x00 為字符串結(jié)束。
int b=sizeof(str);//而b=20; >>>> sizeof 計算的則是分配的數(shù)組 str[20] 所占的內(nèi)存空間的大小,不受里面存儲的內(nèi)容改變。
上面是對靜態(tài)數(shù)組處理的結(jié)果,如果是對指針,結(jié)果就不一樣了
char* ss ="0123456789";
sizeof(ss) 結(jié)果4 ===》ss是指向字符串常量的字符指針,sizeof 獲得的是一個指針的之所占的空間,應(yīng)該是 長整型的,所以是4
sizeof(*ss) 結(jié)果1 ===》*ss是第一個字符 其實就是獲得了字符串的第一位'0' 所占的內(nèi)存空間,是char類 型的,占了 1 位
strlen(ss)= 10 >>>>?strlen 計算字符串的長度,以結(jié)束符 0x00 為字符串結(jié)束。
面試題:
1、sizeof( int) *p 表示什么意思?
需要明白 sizeof 后跟數(shù)據(jù)類型,必須要用圓括號括住的,強制類型轉(zhuǎn)換也應(yīng)該是 (int*) p,所以這句話所表達的意思是 sizeof (int) 乘以 p
#include <stdio.h>int main (void) {int p = 1;printf ("%d\n", sizeof (int)*p); return 0; } 輸出結(jié)果: 4 #include <stdio.h>int main (void) {int p = 1;printf ("%d\n", sizeof ((int *)p)); //強制類型轉(zhuǎn)換return 0; } 輸出結(jié)果: 4
2、在 32 位系統(tǒng)下:
int *p = NULL;
sizeof(p)的值是多少?
sizeof(*p)呢?
sizeof (p) = 4; ?因為 p為指針,32位系統(tǒng) 指針所占字節(jié)為 4個字節(jié)
sizeof (*p) = 4; ?因為 *p 為 指針所指向的變量為int類型,整型為 4個字節(jié)
#include <stdio.h>int main (void) {short *p = NULL;int i = sizeof (p);int j = sizeof (*p);printf ("i = %d, j = %d\n", i, j);return 0; } 輸出結(jié)果: i = 4, j = 23、int a[100];
sizeof (a) 的值是多少?
sizeof(a[100])呢? //請尤其注意本例。
sizeof(&a)呢?
sizeof(&a[0])呢?
sizeof (a) = 400; ?因為 a是類型為整型、有100個元素的數(shù)組,所占內(nèi)存為400個字節(jié)
sizeof (a[100]) = 4; ?因為 a[100] 為數(shù)組的第100元素的值該值為 int 類型,所占內(nèi)存為4個字節(jié)。
sizeof (&a) = 4; ?因為 &a 為數(shù)組的地址即指針,32位系統(tǒng) 指針所占字節(jié)為 4個字節(jié)
sizeof (&a[0]) = 4; 因為&a[0] 為數(shù)組的首元素的地址即指針,32位系統(tǒng) 指針所占字節(jié)為 4個字節(jié)
#include <stdio.h>int main (void) {int a[100];printf ("sizeof (a) = %d\n", sizeof (a));printf ("sizeof (a[100] = %d\n", sizeof (a[100]));printf ("sizoef (&a) = %d\n", sizeof (&a));printf ("sizeof (&a[0] = %d\n)", sizeof (&a[0]));return 0; } 輸出結(jié)果: sizeof (a) = 400 sizeof (a[100] = 4 sizoef (&a) = 4 sizeof (&a[0] = 4
4、int b[100];
void fun(int b[100])
{
sizeof(b);// sizeof (b) 的值是多少?
}
sizeof (b) = 4; ?因為函數(shù)中的數(shù)組形參或函數(shù)類型的形參,sizeof給出其指針的大小。參數(shù)傳遞數(shù)組永遠都是傳遞指向數(shù)組首元素的指針。
#include <stdio.h>void fun (int b[100]) //指針做形參 {printf ("sizeof (b) = %d\n", sizeof (b)); }int main (void) {int a[10];fun (a);return 0; } 輸出結(jié)果: sizeof (b) = 4 #include <stdio.h> void foo (void) {printf ("111\n"); }void fun (foo) //函數(shù)做形參 {printf ("sizeof (foo) = %d\n", sizeof (foo)); } int main (void) {fun ();return 0; } 輸出結(jié)果: sizeof (foo) = 4
總結(jié)
以上是生活随笔為你收集整理的C语言再学习 -- 关键字sizeof与strlen的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【C语言结构体】
- 下一篇: Word2Vec学习笔记(三)续