C語言新增stdint.h頭文件的討論什麼是快類型什麼是小類型

2020-12-18 酷扯兒

本文轉載自【微信公眾號:雲深之無跡,ID:TT1827652464】經微信公眾號授權轉載,如需轉載與原文作者聯繫

雖說C語言是一門很成熟的程式語言,但是近些年來也是有所發展的,從早期的C89到後來的C99、C11等新標準,C語言逐步增加了許多好用的功能,例如新標準頭文件「stdint.h」的添加。

如果程式設計師希望寫出可移植的C語言程序,首先最重要的一點是不能假定位寬。C語言標準並沒有明確指定的 short、int、long 等類型的位寬,因此可能在某些平臺 sizeof(int) 等於 2,在其他平臺 sizeof(int) 等於 4,所以如果編寫的C語言代碼假定 sizeof(int) 是一個固定值,顯然就屬於不可移植的代碼。

為了解決這樣的問題,在新標準文件「stdint.h」 之前,程式設計師必須做些額外的工作,以確定C語言代碼運行的平臺的各種數據位寬,這樣的工作著實煩人,稍不留神就會出錯。

「stdint.h」頭文件的添加就是為了便於程式設計師寫出不假定位寬的程序的。其內部通過 typedef 和宏判斷定義了不少好用的整數類型,例如 int8_t 類型表示 8 位的有符號的整數類型,uint32_t 則表示 32 位的無符號的整數類型。類似的,還有 int16_t、int64_t、uint64_t 等類型,都是比較好理解的。

C語言中的「快」類型

不過,如果讀者打開 stdint.h 頭文件,應該能夠看到一些更有趣的類型,如下圖:

可以看出,這些類型被稱作「fast type」,類型名中也有 fast 的字樣(如 int_fast16_t),直譯成中文即「快類型」,那麼它們到底有什麼含義呢?

觀察力敏銳的讀者應該發現了,int_fast16_t 和 int_fast32_t 其實是一樣的,以上圖黃框為例,它們都表示 int 類型,這是怎麼回事呢?int 類型怎麼能同時表示 16 位寬和 32 位寬的整數類型呢?

int 類型當然不能同時表示兩種位寬的整數類型,事實上,int_fastxx_t 類型並不是準確的 xx 位寬類型,它表示不低於 xx 位寬的類型,因此,只要 int 的位寬大於或者等於 32 位,它就能同時表示 int_fast16_t 和 int_fast32_t 類型。

有讀者看到這裡可能會有疑問,如果 int 的位寬等於 32,那麼使用它來表示 16 位寬的 int_fast16_t 整數類型,不是造成資源浪費了嗎?

其實讀者應將注意力放在「fast」一詞上。CPU 從內存取數據一般是逐字取得,這裡的「字」並不是字節的意思,在 32 位主機上,字長常常是 4 個字節,也即 CPU 單次取出數據的最小單位是 4 個字節。

字長也可以理解為 CPU 讀取數據的「步長」。

也就是說,CPU 讀取數據的「步長」是字長(下文以4位元組為例),也就是說假設這次讀取了地址 0~3 的數據,接下來若是希望讀取相鄰的數據,最接近的地址也得是地址 4~7。其實從這裡可以看出,CPU 每次讀取數據的起始地址都是字長的整數倍。

這也是「數據對齊」的原因——為了CPU讀取數據的效率。

如果需要讀取的數據只有一個字節(char 型),那麼顯然,無論該字節放在哪裡,它總是在某個字長段的範圍內的(例如地址 0~3,地址 4~7 內),此時 CPU 一次就能讀取完畢。

如果需要讀取的數據有兩個字節(16bits),情況就不同了——它的地址可能是 3~4,而 CPU 讀取數據的「步長」是 4 個字節,若要讀取該值,CPU 只能先讀取 0~3 字節的數據,再讀取 4~7 字節的數據,最後還需要組合拼湊,才能得到該值。這樣的一系列操作顯然非常低效。

所以 stdint.h 將「快」類型定義為字長的整數倍的意圖就一目了然了,無非就是犧牲一些「空間」換取「時間」。當然了,讀者在使用「快類型」時需要注意:int_fast16_t 並不一定恰好是 16 位寬,它只是不少於 16 位寬的類型。

C語言中的「小」類型

前面提到,int_fastxx_t 類型犧牲了「空間」換取「時間」,如果在某個C語言項目中,「空間」效率並不是特別重要,而「空間」效率卻非常重要,那麼 int_fastxx_t 類型顯然就不合適了。此時可以使用 stdint.h 中定義的 「small type」,也即「小類型」。

int_leastxx_t 系列的數據類型基本上保證了其恰好是 xx 位寬,避免了空間浪費,但是按照前文的分析,「小類型」付出的代價是損失了一部分時間效率。

小結

本文主要討論了C語言新增頭文件「stdint.h」中定義的幾種整數類型,並在此基礎上討論了「時間」效率和「空間」效率的矛盾。事實上,"stdint.h" 頭文件中還定義了其他一些好用的宏,比如整數指針,各個數據類型的最大值和最小值等等,留給讀者自己查看了。

// 詳解下各種類型

https://stackoverflow.com/questions/9239558/what-is-the-difference-between-intxx-t-and-int-fastxx-t

https://stackoverflow.com/questions/tagged/c?tab=votes&page=124&pagesi

相關焦點

  • 很多程式設計師都不知道,C語言中還有「快類型」和「小類型」
    雖說C語言是一門很成熟的程式語言,但是近些年來也是有所發展的,從早期的C89到後來的C99、C11等新標準,C語言逐步增加了許多好用的功能,例如新標準頭文件「stdint.h」的添加。為了解決這樣的問題,在新標準文件「stdint.h」 之前,程式設計師必須做些額外的工作,以確定C語言代碼運行的平臺的各種數據位寬,這樣的工作著實煩人,稍不留神就會出錯。「stdint.h」頭文件的添加就是為了便於程式設計師寫出不假定位寬的程序的。
  • C語言頭文件被include後都發生了什麼?為何不能在頭文件定義變量
    頭文件是C語言的一個重要組成部分,這種類型的文件名一般以 .h 結尾,h 表示 header,因此被稱為「頭文件」。頭文件裡一般存放公開的函數原型,數據類型等內容,其他模塊需要使用這些函數或者數據類型時,只需包含相應頭文件即可。
  • C語言項目中.h和.c文件的關係和概念
    因為這個新文件,經常被放在.c(.cpp)文件的頭部,所以就給它起名叫做「頭文件」,擴展名是.h。 頭文件的作用的簡短描述: 用戶只需要按照頭文件中的接口聲明來調用庫功能,而不必關心接口怎麼實現的。編譯器會從庫中提取相應的代碼。 2.頭文件能加強類型安全檢查。如果某個接口被實現或被使用時,其方式與頭文件中的聲明不一致,編譯器就會指出錯誤,這一簡單的規則能大大減輕程式設計師調試、改錯的負擔。
  • C語言const 關鍵字
    我們看看下面這個代碼#include "stdio.h"#include "stdint.h"void printTwo(uint32_t a, uint64_t b);void printTwo(const uint32_t a, const uint64_t b) { printf("%d %d\n", a, b);}int
  • C語言中常用的幾個頭文件及庫函數
    來源:https://www.jb51.net/article/124594.htm這篇文章主要介紹了C語言中常用的幾個頭文件及庫函數的相關資料
  • C語言這些常用的標準庫(頭文件),你不得不知道...
    下面小編就來分享一下C語言常見的一些標準庫。標準頭文件包括:<asset.h><ctype.h><errno.h><float.h><limits.h><locale.h><math.h><stdio.h><signal.h><time.h><stddef.h>
  • clang_intprt_t類型探究
    return 0;}只看op == LC這段代碼,ax是一個int類型,存放的值是char *指針類型地址,取完該地址所在的值再賦給變量ax但是如此寫代碼,vim的youcomplete插件一直報錯那就舉個例子//test.c#include <stdio.h>int main() {    int a =
  • C語言的頭文件包含竟然有那麼多講究!
    曾以為自己寫C語言已經輕車熟路了,特別是對軟體文件的工程管理上,因為心裡對自己的代碼編寫風格還是有自信的。(畢竟剛畢業時老大對我最初的訓練就是編碼格式的規範化處理)曾以為,一個.c文件對應一個.h文件,.c文件只包含它自身的.h文件就好,若.c文件中用到其他文件中的內容,則.h文件把用到的頭文件包含進來就可以了。
  • C語言簡明教程(二)數據類型
    >數據類型實驗簡介從本章開始我們將要引入大量的 C 語言程序案例,把算法和語法結合起來,通過引導大家由淺入深地編寫 C 程序,讓大家掌握 C 語言。3-1.c 是一個簡單的計算程序,通過定義變量讓用戶可以自由設定 a 和 b 的值,之後通過 c = a + b; 這條語句實現把 a 和 b 的和計算出來並賦值給 c。究竟什麼是變量,什麼是常量呢?接下來我們來一一講述。常量顧名思義,值不能被改變的量稱為常量。
  • C 語言學習之變量、數據類型
    變量C 語言是強數據類型語言
  • 物聯網開發筆記——嵌入式開發之Linux系統中C語言數據類型
    嵌入式開發學習C語言打下基礎。本節介紹《Linux系統中C語言數據類型》。1 數據類型分類short、int、long、char、float、double 這六個關鍵字代表C 語言裡的六種基本數據類型。
  • C語言面試54題
    Char, int, long int數據類型有這個特性。Further float, double和long double數據類型沒有這個特性。第14題, 說一下c語言的頭文件和用途。頭文件存放了原型函數的定義。這個文件又稱為庫文件。
  • C語言知識點概要第二部分(數據類型)
    C語言變量必須先定義後使用(指定變量的類型),變量的定義只能放在函數的說明部分或者複合語句的開始位置#include<stdio.h>int main(){ int a=1; short b=2; long c=2; long long d=4; printf(
  • C語言編程實例:一鍵清空目標文件夾|整人小程序
    前言今天的文章跟大家講一下,C語言中的文件操作——遍歷文件夾和刪除文件,以及如何應用這兩個技能來寫一個有趣的小程序,這篇文章涉及的知識點很少,也很簡單,所以這篇文章就當做給小白們的小教程吧,讓你們每天都能充滿激情地學習編程,擺脫學習C語言枯燥乏味的過程。
  • C語言入門
    這些都可以用來編寫C語言程序。2、什麼是編譯器通過編輯器寫出的代碼只是源程序的文本文件,必須經過編譯之後才可以在電腦上運行。常用的編譯器有:microsoft C++Compiler、gcc等。3、什麼是集成開發環境(IDE)集成開發環境就是為程序開發提供的環境應用軟體,裡面集成了編輯器和編譯器。
  • 你所不知道的C語言高級用法
    一般的方法是採用固定長度的類型比如定義在C99頭文件stdint.h中的uint16_t,int32_t,uint_least16_t,uint_fast16_t等。下面這段代碼可以帶你領會malloc,calloc,realloc,free的用法:#include <stdio.h> #include <stdint.h> #include <malloc.h> #include <errno.h>  #define VECTOR_OK            0 #define VECTOR_NULL_ERROR
  • 《C語言入門指南》中篇
    ->==使用頭文件==頭文件基本概念1、 頭文件是擴展名為 .h 的文件,包含了 C 函數聲明和宏定義,被多個源文件中引用共享。有兩種類型的頭文件:==程式設計師編寫的頭文件==和==C標準庫自帶的頭文件== 2、 在程序中要使用頭文件,需要使用 C ==預處理指令 #include==來引用它。
  • 說一說C語言中的變量存儲類型——「extern」
    1、 回顧C語言變量C語言中變量值的存儲位置有兩類:CPU的寄存器和內存。變量存儲類型關係到其存儲位置,除了register型存儲在CPU寄存器中,C語言提供的其它三種存儲類型(auto型、static型、extern型)的變量均存儲在內存中。
  • C語言不完整類型
    這個特性可以認為是 C 語言的封裝。使用示例:#point.htypedef struct point POINT;POINT * new_point(int x, int y);void free_point(POINT *a);int cal_point_value(POINT *a);#point.c#include
  • C 語言面向對象編程 - 繼承
    >在頭文件 coordinate.h 裡,聲明一個位置類,類裡面提供了坐標屬性 x 和 y,還提供了屬性的操作函數指針。頭源文件 coordinate.c #include "stdio.h"#include "stdlib.h"#include "string.h"#include "inc/coordinate.h"static void coordinate_moveby(struct coordinate *p_coordiante,short