感覺C語言中,任何一個函數、宏,或者其他概念,拿出來仔細分析,都能包含很多知識點,稍微不注意,立馬入坑!看了好幾篇博客,感覺各位大佬寫的都挺好!作爲新人的我,簡單總結下!
1.sizeof定義及用法:
1.定義:
sizeof是C語言的一種單目操作符,如C語言的其他操作符++、–等。它並不是函數。sizeof操作符以字節形式給出了其操作數的存儲大小。操作數可以是一個表達式或括在括號內的類型名。操作數的存儲大小由操作數的類型決定。作用就是返回一個對象或者類型所佔的內存字節數。
2.用法:
sizeof有三種語法形式:
1) sizeof( object ); // sizeof( 對象 );
2) sizeof( type_name ); // sizeof( 類型 );
3) sizeof object; // sizeof 對象,無括號用法
因爲第三種用法,sizeof後面只能跟 對象名,不能跟 數據類型,所以容易出錯。不建議使用,後續的內容就默認忽略了這種用法!
要點分析:
1.sizeof(),無論計算的是什麼內容,我們先判斷是否是對象名(數組名、變量名、結構體名,函數名等等),如果是,則計算的大小就是變量定義時候佔用的大小;如果不是這些,都歸類爲其他類型。
2.其他類型,無論是指針、指針變量、地址、具體數值等等,sizeof()計算的流程都是,先找出這些類型的具體數據類型(int、 char 、short、double等),然後再計算佔用空間的大小。
2.習題測試:
1.數組 & 數組名相關
以下代碼展示,都在32位編譯環境中實現
#include <stdio.h>
int main() {
int arr[100];
printf("%d \n", sizeof(arr)); // arr是數組名
printf("%d \n", sizeof(&arr)); // &arr是數組名的地址,即首元素地址
printf("%d \n", sizeof(arr[100])); // arr數組的第100個元素的值
printf("%d \n", sizeof(&arr[100])); // arr數組的第100個元素的地址
printf("======================\n");
int a[10] = { 1, 2, 3, 4, 5 };
printf("%d \n", sizeof(a));
printf("%d \n", sizeof(&a));
printf("%d \n", sizeof(a[2]));
printf("%d \n", sizeof(&a[2]));
printf("======================\n");
int b[] = { 1, 2, 3, 4, 5 };
printf("%d \n", sizeof(b));
printf("%d \n", sizeof(&b));
printf("%d \n", sizeof(b[2]));
printf("%d \n", sizeof(&b[2]));
};
400 // 4 * 100 = 400
4
4
4
======================
40 // 4 * 10 = 40
4
4
4
======================
20 // 4 * 5 = 20
4
4
4
- 根據如上分析,只有arr、a、b是對象名,即數組名,計算這類sizeof的大小,都是計算對象定義時候的所在的內存大小。因爲b數組在初試化的時候才知道具體大小,這個算特殊情況。
- &arr、&a、&b這個是取數組名的地址,即取數組首元素的地址。我們知道,指針變量就是存放的各個元素的地址,而指針在32位系統中都佔用4個字節大小,所以,所有的地址佔用的空間大小都爲4個字節(32位)。
- arr[100] 、a[2]、b[2]類型這樣的,最終取到的是具體的值,而數組中存放的都是int類型的元素。所以最終就變爲了sizeof(0)、sizeof(3),類似這樣的取值,最終轉換爲sizeof(int)這樣計算,暫用字節的大小。
2.指針變量 & *指針
#include <stdio.h>
int main() {
int* p = NULL;
printf("%d \n", sizeof(p));
printf("%d \n", sizeof(*p));
printf("======================\n");
int a[10] = { 1, 2, 3, 4, 5 };
p = &a;
printf("%d \n", sizeof(p)); // p是指針變量,地址大小一直都是4個字節
printf("%d %d\n", sizeof(*p), *p); // *p是首元素的值,
printf("%d %d\n", sizeof(p[1]),p[1]); // p[1]也可以當做a[1]使用,獲取第二個元素的值
};
4
4
======================
4
4 1
4 2
3.字符 & 字符數組
因爲C語言中沒有字符串數據類型,用字符數組模擬的字符串,但中間有個隱患。如果字符數組空間足夠大時候,字符數組會以“\0”結尾,如果沒有足夠空間,則沒有“\0”.
#include <stdio.h>
int main() {
char aa[5] = "alien"; // 字符數組,定義時設置的空間剛好夠初始化使用,那\0就不添加進去了
printf("%d \n", sizeof(aa));
printf("%d \n", sizeof(&aa));
printf("======================\n");
char a[10] = "alien"; // 字符數組,a的時候就設定了a的大小
printf("%d \n", sizeof(a));
printf("%d \n", sizeof(&a));
printf("======================\n");
char b[] = "alien"; // 字符數組,定義的時候沒設置空間,但初始化的時候就會默認添加\0
printf("%d \n", sizeof(b));
printf("%d \n", sizeof(&b));
printf("======================\n");
char c = 'c'; // 字符,默認佔用1字節
printf("%d \n", sizeof(c));
printf("%d \n", sizeof(&c));
};
5
4
======================
10
4
======================
6
4
======================
1
4
4.函數
1.數組傳遞給函數:
#include <stdio.h>
int a[10];
int main(int a[10]) { //
printf("%d \n", sizeof(a));
printf("%d \n", sizeof(&a));
};
4
4
重點:
- 在C語言中,當一維數組作爲函數參數的時候,編譯器總是把它解析成一個指向其首元素地址的指針。
- 通俗點說:在c語言中,你如果想傳遞一維數組,編譯器會把你的這個數組,當做一個指針傳遞到函數中
- 有關這方面,我在另一篇博客中有詳細介紹:
2.sizeof(函數名)
#include <stdio.h>
int f1() {
return 0;
};
double f2() { return 0.0; };
void f3(){};
int main() {
printf("%d \n", sizeof(f1())); // f1()返回值爲int,因此被認爲是int
printf("%d \n", sizeof(f2())); // f2()返回值爲double,因此被認爲是double
//printf("%d \n", sizeof(f3())); // 錯誤!無法對void類型使用sizeof
//printf("%d \n", sizeof(f1)); // 錯誤!無法對函數指針使用sizeof
//printf("%d \n", sizeof(*f2)); // *f2,和f2()等價,因爲可以看作object,所以括號不是必要的。被認爲是double
}
4
8
- 函數返回什麼類型的數據,就按這個數據類型計算。具體是:sizeof(函數名()),相當於調用這個函數的結果,並計算佔用空間大小。
- 有關*f2 和f2()等價的問題,我在C 和C++環境都嘗試了,都無法編譯通過。後續再進一步研究,然後再補充一下(如果哪位大佬看到了,煩請告知一二,感激不盡!)
- 上面未知問題,來源:https://blog.csdn.net/petib_wangwei/article/details/38685253