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