關於size t的學習

2021-09-12 19:38:15 字數 4548 閱讀 1027

size_t概念:是一種與資料相關的無符號整形,需要注意的是在不同的型別的作業系統中其值的大小是不一樣的,其可以記憶體中任意大小的物件

size_t的概述:是存在與cstddef中的,在c++編譯的過程中需要將該標頭檔案包含進來

size_t的由來:純粹是為了適應多個平台的操作,即跨平台的操作

在32位的作業系統裡面size_t佔4個位元組,在64位的作業系統裡面佔8個位元組。但是實際上在操作的時候卻有一定的變化

以上是在64位作業系統裡面執行的情況如下:

cout<

疑難解答:在我們實際程式設計的時候,size_t不一定全部按照計算機作業系統來判定,實際上會考慮你的編譯環境,出現上述情況的原因是因為我們在編譯的時候選擇的編譯環境是出於32位的編譯環境如下:

紅色方框表示的是我們目前生成的程式是32位的程式,所以上面的size_t佔4個位元組,那麼如果選擇要生成的程式是64位的我們應該如何操作呢,實際的運**況如下:

以上便是為了生存64位的程式而選擇的編譯器,同樣是將以上**進行編譯,得到的結果如下:

所以實際上size_t並不是實際上全靠作業系統來決定其大小,實際情況是既與作業系統有關也與變異的程式型別有關,32位的程式既可以在64位的作業系統上面執行,也可以在32位的作業系統上面執行,但是64位的程式卻只能在64位的作業系統上面執行

備註,下面是在vs中位size_t而定義的一條**:

#ifdef _win64

typedef unsigned __int64 size_t;

#else

typedef _w64 unsigned int size_t;

#endif

下面是乙個關於size_t重要的使用場景,因為寫的太好了,這裡直接引用,附上部落格位址

前言:使用size_t可能會提高**的可移植性、有效性或者可讀性,或許同時提高這三者。

在標準c庫中的許多函式使用的引數或者返回值都是表示的用位元組表示的物件大小,比如說malloc(n) 函式的引數n指明了需要申請的空間大小,還有memcpy(s1, s2, n)的最後乙個引數,表明需要複製的記憶體大小,strlen(s)函式的返回值表明了以』\0』結尾的字串的長度(不包括』\0』),其返回值並不是該字串的實際長度,因為要去掉』\0』。

或許你會認為這些引數或者返回值應該被申明為int型別(或者long或者unsigned),但是事實上並不是。c標準中將他們定義為size_t。標準中記載malloc的申明應該出現在,定義為:

void *malloc(size_t n);
memcpy和strlen的申明應該出現在中:
void *memcpy(void *s1, void const *s2, size_t n);

size_t strlen(char const *s);

size_t還經常出現在c++標準庫中,此外,c++庫中經常會使用乙個相似的型別size_type,用的可能比size_t還要多。

據我所知,大部分的c和c++程式設計師害怕這些庫使用size_t,因為他們不知道size_t代表什麼或者為什麼這些庫需要使用它,歸根結底,原因在於他們什麼時候什麼地方需要用到它。

可移植性問題

早期的c語言(由brian kernighan 和 dennis ritchie 在the c programming language書中所寫,prentice-hall, 1978)並沒有提供size_t型別,c標準委員會為了解決移植性問題將size_t引入,舉例如下:

讓我們來寫乙個可移植的標準memcpy函式,我們將會看到一些不同的申明和它們在不同平台不同大小的位址空間上編譯下的情況。

回憶memcpy(s1, s2, n)函式,它將s2指向位址開始的n個位元組拷貝到s2指向的位址,返回s1,這個函式可以拷貝任何資料型別,所以引數和返回值的型別應該為可以指向任何型別的void*,同時,源位址不應該被改變,所以第二個引數s2型別應該為const void*,這些都不是問題。

真正的問題在於我們如何申明第三個引數,它代表了源物件的大小,我相信大部分程式設計師都會選擇int:

void *memcpy(void *s1, void const *s2, int n);
使用int型別在大部分情況下都是可以的,但是並不是所有情況下都可以。int是有符號的,它可以表示負數,但是,大小不可能是複數。所以我們可以使用unsigned int代替它讓第三個引數表示的範圍更大。

在大部分機器上,unsigned int的最大值要比int的最大值大兩倍,比如說再也給16位的機器上,unsigned int的最大值為65535,int的最大值為32767。

儘管int型別的大小依賴於c編譯器的實現,但是在給定的平台上int物件的大小和unsigned int物件的大小是一樣的。因此,使用unsigned int修飾第三個引數的代價與int是相同的:

void *memcpy(void *s1, void const *s2, unsigned int n);
這樣似乎沒有問題了,unsigned int可以表示最大型別的物件大小了,這種情況只有在整形和指標型別具有相同大小的情況下,比如說在ip16中,整形和指標都佔2個位元組(16位),而在ip32上面,整形和指標都佔4個位元組(32位)。(參見下面c資料模型表示法)

c資料模型表示法   最近,我偶然發現幾篇文章,他們使用簡明的標記來表述不同目標平台下c語言資料的實現。我還沒有找到這個標記的**,正式的語法,甚至連名字都沒有,但他似乎很簡單,即使沒有正規的定義也可以很容易使用起來。這些標記的一邊形式形如:   i ni l nl ll nll p np。   其中每個大寫字母(或成對出現)代表乙個c的資料型別,每乙個對應的n是這個型別包含的位數。i代表int,l代表long,ll代表long long,以及p代表指標(指向資料,而不是函式)。每個字母和數字都是可選的。   例如,i16p32架構支援16位int和32位指標型別,沒有指明是否支援long或者long long。如果兩個連續的型別具有相同的大小,通常省略第乙個數字。例如,你可以將i16l32p32寫為i16lp32,這是乙個支援16位int,32位long,和32位指標的架構。   標記通常把字母分類在一起,所以可以按照其對應的數字公升序排列。例如,il32ll64p32表示支援32位int,32位long,64位long long和32位指標的架構;然而,通常寫作ilp32ll64。

不幸的是,這種memcpy的申明在i16lp32架構上(整形是16-bit 長整形和指標型別時32-bits)顯得不夠用了,比如說摩托羅拉第一代處理器68000,在這種情況下,處理器可能拷貝的資料大於65535個位元組,但是這個函式第三個引數n不能處理這麼大的資料。

什麼?你說很容易就可以改正?只需要把memcpy的第三個引數的型別修改一下:

你可以在i16lp32目標架構上使用這個函式了,它可以處理更大的資料。而且在ip16和ip32平台上效果也還行,說明它確實給出了memcpy的一種移植性較好的申明。但是,在ip16平台上相比於使用unsigned int,你使用unsigned long可能會使你的**執行效率大打折扣(**量變大而且執行變慢)。

在標準c中規定,長整形(無論無符號或者有符號)至少占用32位,因此在ip16平台上支援標準c的話,那麼它一定是ip16l32 平台。這些平台通常使用一對16位的字來實現32位的長整形。在這種情況下,移動乙個長整形需要兩條機器指令,每條移動乙個16位的塊。事實上,這個平台上的大部分的32位操作都需要至上兩條指令。

因此,以可移植性為名將memcpy的第三個引數申明為unsigned long而降低某些平台的效能是我們所不希望看到的。使用size_t可以有效避免這種情況。

size_t型別是乙個型別定義,通常將一些無符號的整形定義為size_t,比如說unsigned int或者unsigned long,甚至unsigned long long。每乙個標準c實現應該選擇足夠大的無符號整形來代表該平台上最大可能出現的物件大小。

size_t的定義在, , , , 和這些標準c標頭檔案中,也出現在相應的c++標頭檔案, 等等中,你應該在你的標頭檔案中至少包含乙個這樣的標頭檔案在使用size_t之前。

包含以上任何c標頭檔案(由c或c++編譯的程式)表明將size_t作為全域性關鍵字。包含以上任何c++標頭檔案(當你只能在c++中做某種操作時)表明將size_t作為std命名空間的成員。

根據定義,size_t是sizeof關鍵字(注:sizeof是關鍵字,並非運算子)運算結果的型別。所以,應當通過適當的方式宣告n來完成賦值:

n = sizeof(thing);
考慮到可移植性和程式效率,n應該被申明為size_t型別。類似的,下面的foo函式的引數也應當被申明為sizeof:

foo(sizeof(thing));
引數中帶有size_t的函式通常會含有區域性變數用來對陣列的大小或者索引進行計算,在這種情況下,size_t是個不錯的選擇。

適當地使用size_t還會使你的**變得如同自帶文件。當你看到乙個物件宣告為size_t型別,你馬上就知道它代表位元組大小或陣列索引,而不是錯誤**或者是乙個普通的算術值。

關於size t型別的整理

因為用的比較多,所以我決定整理一下size t的知識點。其實說白了就是一種資料型別,在標準c庫中定義的,應為unsigned int,在64位系統中為 long unsigned int。size t為什麼麻煩呢,因為它引起了我程式的問題,也是一種玄學的bug typename is not all...

size t型別的含義

size t乙個基本的無符號整數的c c 型別,它的全稱是size type,就是一種用來記錄大小的資料型別,也是sizeof操作符返回的結果型別。size t是在基於無符號整數memsize型別的c c 的標準庫中定義的。c語言中,此型別位於標頭檔案stddef.h中,而在c 中,則位於cstdd...

size type 和 size t 的區別

string st the expense of spirit n cout the size of 那麼size 這個函式返回的型別?一定要記住,絕對不是整形,而是 size type 型別的,所以千萬不要把 size 的返回值賦給乙個 int變數。那麼 size type 到底是一種什麼樣的型別...