16 C 語言布爾類型與 sizeof 運算符詳解:布爾類型的三種聲明方式、執行時間、賦值規則

1 布爾類型

1.1 布爾類型概述

????????布爾類型用于表示邏輯上的真(true)和假(false)兩種狀態,是編程中條件判斷和邏輯運算的基礎。在 C 語言中,布爾值的表示方式隨著標準的發展而不斷完善。

1.2 布爾類型的三種聲明方式

宏定義方式(C89 及以前版本)

  • 在 C89 及以前的 C 語言標準中,沒有原生的布爾類型。
  • 開發者通常使用宏定義來模擬布爾類型,將 TRUE FALSE 分別定義為 10
  • 這種方式不夠直觀,但能在一定程度上滿足布爾邏輯的需求。
#include <stdio.h>// 宏定義布爾類型
#define BOOL int
#define TRUE 1
#define FALSE 0int main()
{BOOL isPass = FALSE; // 初始化為假BOOL isOk = TRUE;    // 初始化為真printf("isPass=%d, isOk=%d\n", isPass, isOk); // 輸出: isPass=0, isOk=1if (isPass){printf("不會執行\n"); // 條件不滿足,不會執行}if (isOk){printf("會執行\n"); // 條件滿足,會執行}return 0;
}

????????程序在 VS Code 中的運行結果如下所示:

_Bool 類型(C99 標準引入)

  • C99 標準引入了原生的布爾類型 _Bool
  • _Bool 類型只能存儲 0 或 1,任何非 0 值賦給 _Bool 變量都會被隱式轉換為 1(真)
  • 這種方式比宏定義更規范,但代碼可讀性稍差,因為通常需要輸出為整數形式。
#include <stdio.h>int main()
{_Bool isPass = 0;   // 初始化為假// _Bool isOk = 1;  // 初始化為真_Bool isOk = -4;    // 非 0 值被轉換為 1(真)printf("isPass=%d, isOk=%d\n", isPass, isOk); // 輸出: isPass=0, isOk=1if (isPass){printf("不會執行\n"); // 條件不滿足,不會執行}if (isOk){printf("會執行\n"); // 條件滿足,會執行}return 0;
}

????????程序在 VS Code 中的運行結果如下所示:

bool 類型(通過 stdbool.h 頭文件)

  • C99 標準還提供了 <stdbool.h> 頭文件其中定義了 bool 類型作為 _Bool 的別名
  • 同時定義了 true 和 false 宏,分別表示 1 和 0,使得代碼更加直觀易讀。
  • 這是現代 C 編程中推薦使用的布爾類型表示方式。
#include <stdio.h>
#include <stdbool.h> // 包含布爾類型定義int main()
{bool isPass = false; // 初始化為假bool isOk = true;    // 初始化為真printf("isPass=%d, isOk=%d\n", isPass, isOk); // 輸出: isPass=0, isOk=1if (isPass){printf("不會執行\n"); // 條件不滿足,不會執行}if (isOk){printf("會執行\n"); // 條件滿足,會執行}return 0;
}

????????程序在 VS Code 中的運行結果如下所示:

????????我們可以通過 VS Code 查看 <stdbool.h> 的源代碼。將鼠標放在 stdbool.h 或 true 或 false 上,按住 Ctrl 鍵并點擊鼠標左鍵即可查看其實現。<stdbool.h> 的源代碼片段通常如下:

????????這進一步驗證了 bool 是 _Bool 的別名,true 和 false 分別對應 1 和 0。?

1.3?三種聲明方式的執行時間

宏定義方式

  • 執行時間:
    • 宏定義是在預處理階段執行的。預處理器會在編譯之前處理所有的宏定義、文件包含等指令。
    • 在預處理階段,所有的宏定義會被替換為對應的文本。例如,BOOL 會被替換為 int,TRUE 會被替換為 1,FALSE 會被替換為 0。
  • 特點:
    • 宏定義不會引入新的類型,只是簡單的文本替換。
    • 由于是在預處理階段完成,因此在編譯階段,編譯器看到的已經是替換后的代碼。

_Bool 類型

  • 執行時間:
    • _Bool 類型的處理是在編譯階段完成的
    • 編譯器會識別 _Bool 類型,并在生成目標代碼時進行相應的處理。
  • 特點:
    • _Bool 是 C 語言原生的布爾類型,提供了更好的類型安全性。
    • 編譯器會在編譯階段對 _Bool 類型的變量進行優化,確保其只存儲 0 或 1。

bool 類型

  • 執行時間:
    • bool 類型的處理也是在編譯階段完成的
    • 當包含 <stdbool.h> 頭文件時,預處理器會將 bool 替換為 _Bool,true 替換為 1,false 替換為 0。
    • 編譯器在編譯階段會識別 _Bool 類型,并進行相應的處理。
  • 特點:
    • bool 是 _Bool 的別名,提供了更直觀和可讀的布爾類型定義。
    • 使用 <stdbool.h> 是現代 C 編程中推薦的方式,因為它提高了代碼的可讀性和一致性。

執行時間總結

方式處理階段特點
宏定義預處理階段簡單文本替換,無類型檢查,靈活性高但安全性低
_Bool 類型編譯階段原生布爾類型,類型安全,編譯器優化
bool 類型編譯階段_Bool 的別名,通過 <stdbool.h> 提供,直觀可讀,推薦使用

1.4?布爾類型的賦值規則

接受任何整數值

  • 布爾變量可以接受任何整數值(如 char、short、int、long 等類型)或任何可隱式轉換為整數的表達式(如算術運算、位運算、比較運算等)。
  • 賦值時,編譯器會自動將值轉換為 0(false)或 1(true),無需手動處理。

非零值視為 true(存儲為 1)

  • 任何非零值(包括正整數、負整數、大整數、甚至超出 bool 存儲范圍的值)都會被視為 true,并存儲為 1
  • bool 的存儲大小是固定的(通常為 1 字節,即 _Bool 類型),但賦值時不會因值過大而報錯或截斷
  • 編譯器會自動轉換:
    • 無論賦值 1、42 還是 1000000,最終存儲的值只能是 0 或 1。
    • 這是因為 bool 類型的本質是邏輯值,而非數值,編譯器會隱式地將任何非零值轉換為 1
#include <stdio.h>
#include <stdbool.h>int main()
{bool b1 = 42;      // 42 → true(存儲為 1)bool b2 = -1;      // -1 → true(存儲為 1)bool b3 = 1000000; // 1,000,000 → true(存儲為 1)printf("b1=%d (實際存儲值: %d)\n", b1, b1); // 輸出: b1=1 (實際存儲值: 1)printf("b2=%d (實際存儲值: %d)\n", b2, b2); // 輸出: b2=1 (實際存儲值: 1)printf("b3=%d (實際存儲值: %d)\n", b3, b3); // 輸出: b3=1 (實際存儲值: 1)return 0;
}

????????程序在 VS Code 中的運行結果如下所示:

零值視為 false(存儲為 0)

  • 只有 0 或顯式的 false 會被視為 false,并存儲為 0
#include <stdio.h>
#include <stdbool.h>int main()
{bool b4 = 0;     // 0 → false(存儲為 0)bool b5 = false; // false → false(存儲為 0)printf("b4 = %d\n", b4); // 0printf("b5 = %d\n", b5); // 0return 0;
}

????????程序在 VS Code 中的運行結果如下所示:

規則總結

規則示例存儲值說明
非零值 → true(1)bool b = 42;1任何非零值(包括負數、大數)
零值 → false(0)bool b = 0;0僅 0 或 false
隱式轉換bool b = -1;1編譯器自動處理非零值
  • bool 類型僅存儲 0 或 1,賦值時會自動轉換,無需擔心數值大小。
  • 這一規則確保了布爾邏輯的簡潔性和一致性。

2?sizeof 運算符

????????sizeof 是 C 語言中的一個重要運算符,用于獲取數據類型、變量、字面量或表達式的存儲大小(以字節為單位)

????????它返回一個 size_t 類型的無符號整數值,通常使用 %zu 格式占位符進行輸出。size_t 的具體類型(如 unsigned int 或 unsigned long)由系統和編譯器決定。

2.1?sizeof 運算符的基本用法

????????sizeof 運算符的主要功能是計算內存占用大小,適用于以下場景:

  1. 基本數據類型:如 bool、char、short、int、long、long long、float、double、long double 等。
  2. 變量:直接作用于變量名。
  3. 字面量:直接作用于常量值。
  4. 表達式:計算表達式的存儲大小。

語法形式:

  • 對于基本數據類型或表達式:sizeof 后面必須使用括號包裹,例如?sizeof(int)、sizeof(1 + 1)。
  • 對于變量或字面量:sizeof 后面的括號是可選的,例如 sizeof a 或 sizeof(a)。

2.2?sizeof 的使用場景

計算基本數據類型的大小

????????基本數據類型的大小可能因編譯器和平臺而異。以下是常見數據類型的典型大小:

#include <stdio.h>
#include <stdbool.h> // 包含 bool 類型int main()
{// 使用轉義字符 \t 格式化輸出printf("數據類型\t大小(字節)\n");printf("--------\t-----------\n");// 對于基本數據類型:sizeof 必須使用括號包裹printf("bool \t\t %zu \n", sizeof(bool));              // 通常為 1 字節printf("char \t\t %zu \n", sizeof(char));              // 通常為 1 字節printf("short \t\t %zu \n", sizeof(short));            // 通常為 2 字節printf("int \t\t %zu \n", sizeof(int));                // 通常為 4 字節printf("long \t\t %zu \n", sizeof(long));              // 通常為 4 或 8 字節printf("long long \t %zu \n", sizeof(long long));      // 通常為 8 字節printf("float \t\t %zu \n", sizeof(float));            // 通常為 4 字節printf("double \t\t %zu \n", sizeof(double));          // 通常為 8 字節printf("long double:\t %zu \n", sizeof(long double)); // 通常為 16 字節return 0;
}

????????程序在 VS Code 中的運行結果如下所示:

計算字面量的大小

????????字面量的大小取決于其類型,sizeof 后面的括號是可選的

  • 字符字面量(如 'a'):通常被提升為 int 類型,因此 sizeof('a') 返回 4(字節)
  • 整數和浮點數字面量:大小由其類型決定。例如:
    • 431 是 int 類型,sizeof(431) 返回 4。
    • 4.31 是 double 類型,sizeof 4.31?返回 8。
#include <stdio.h>
#include <stdbool.h>int main()
{// 字符類型字面量:在 C 中字符常量如 'a' 實際上是 int 類型(通常為 4 字節)printf("字符類型字面量('a'):%zu\n", sizeof('a'));     // 輸出通常為 4(bool 提升為 int)printf("布爾類型字面量(true):%zu\n", sizeof(true));   // 輸出通常為 4(bool 提升為 int)printf("布爾類型字面量(false):%zu\n", sizeof(false)); // 輸出通常為 4(bool 提升為 int)// 整型字面量:默認是 int 類型printf("整型字面量(431):%zu\n", sizeof(431)); // 輸出通常為 4(int)// 長整型后綴 L:long int(具體大小依賴平臺)printf("長整型字面量(431L):%zu\n", sizeof(431L)); // 具體大小依賴平臺// 長長整型后綴 LL:long long int(通常為 8 字節)printf("長長整型字面量(431LL):%zu\n", sizeof(431LL)); // 輸出通常為 8(long long)// 單精度浮點數字面量:使用 f 后綴表示 float(通常為 4 字節)printf("單精度浮點型字面量(4.31f):%zu\n", sizeof(4.31f)); // 輸出通常為 4(float)// 雙精度浮點數字面量:默認是 double 類型(通常為 8 字節)printf("雙精度浮點型字面量(4.31):%zu\n", sizeof(4.31)); // 輸出通常為 8(double)// 長雙精度浮點數字面量:使用 L 后綴表示 long double(通常為 16 字節)printf("長雙精度浮點型字面量(4.31L):%zu\n", sizeof(4.31L)); // 輸出通常 16// 對于字面量:sizeof 后面的括號是可選的printf("對于字面量:sizeof 后面的括號是可選的:%zu\n", sizeof true);  // 輸出通常為 4(bool 提升為 int)printf("對于字面量:sizeof 后面的括號是可選的:%zu\n", sizeof 431);   // 輸出通常為 4(int)printf("對于字面量:sizeof 后面的括號是可選的:%zu\n", sizeof 431L);  // 具體大小依賴平臺printf("對于字面量:sizeof 后面的括號是可選的:%zu\n", sizeof 431LL); // 輸出通常為 8(long long)printf("對于字面量:sizeof 后面的括號是可選的:%zu\n", sizeof 4.31f); // 輸出通常為 4(float)printf("對于字面量:sizeof 后面的括號是可選的:%zu\n", sizeof 4.31);  // 輸出通常為 8(double)printf("對于字面量:sizeof 后面的括號是可選的:%zu\n", sizeof 4.31L); // 輸出通常為 16(long double)return 0;
}

????????程序在 VS Code 中的運行結果如下所示:

計算變量的大小

????????變量的大小與其類型一致,sizeof 后面的括號是可選的

#include <stdio.h>int main()
{char a = 'A';             // char 類型變量short b = 66;             // short 類型變量int c = 66;               // int 類型變量long d = 8888888L;        // long 類型變量long long e = 99999999LL; // long long 類型變量float f = 5.6f;           // float 類型變量double g = 10.8;          // double 類型變量long double h = 12.34L;   // long double 類型變量printf("a: %zu \n", sizeof(a)); // 輸出為 1(char 類型)printf("b: %zu \n", sizeof(b)); // 輸出為 2(short 類型)printf("c: %zu \n", sizeof(c)); // 輸出為 4(int 類型)printf("d: %zu \n", sizeof(d)); // 具體大小依賴平臺// 對于變量:sizeof 后面的括號是可選的printf("e: %zu \n", sizeof e); // 輸出為 8(long long 類型)printf("f: %zu \n", sizeof f); // 輸出為 4(float 類型)printf("g: %zu \n", sizeof g); // 輸出為 8(double 類型)printf("h: %zu \n", sizeof h); // 輸出為 16(long double 類型)return 0;
}

????????程序在 VS Code 中的運行結果如下所示:

計算表達式的大小

????????sizeof 也可以用于計算表達式的存儲大小:

#include <stdio.h>int main()
{int d1 = 10;double d2 = 20.0;// printf("表達式(d1 + d2):%zu \n", sizeof d1 + d2);  // 不加括號這里輸出會出問題,printf("表達式(d1 + d2)的存儲大小:%zu \n", sizeof(d1 + d2)); // 加上括號當成一個整體// int 類型和 double 類型相加,結果是 double 類型,所以 sizeof(d1 + d2) 的結果是 8printf("表達式(1 + 2)的存儲大小:%zu \n", sizeof(1 + 2)); // 4return 0;
}

????????程序在 VS Code 中的運行結果如下所示:

2.3 注意事項

  1. 括號的可選性:
    • 對基本數據類型和表達式必須使用括號(如 sizeof(int))
    • 對變量或字面量可省略括號(如 sizeof a)
    • 建議:為了統一規范和代碼可讀性,建議在使用 sizeof 時,始終使用括號,無論是對數據類型、變量、字面量還是表達式。例如:sizeof(int)、sizeof(variableName)、sizeof(42)。
    類型提升:
    • 字符字面量(如 'a')在 sizeof 運算中會被提升為 int 類型
  2. 平臺和編譯器依賴性:
    • 數據類型的大小可能因平臺和編譯器而異(如 long 可能是 4 或 8 字節、long double 可能是 8 字節、10 字節、12 字節或 16 字節)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/81393.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/81393.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/81393.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C++詳解】string各種接口如何使用保姆級攻略

文章目錄 一、string介紹二、string使用構造函數析構函數賦值運算符重載string的遍歷修改方法1、下標[]2、迭代器3、范圍for 迭代器使用詳解const迭代器反向迭代器&#xff08;reverse) Capacity(容量相關)size/lengthmax_sizecapacityclear/emptyshrink_to_fit(縮容)reserve(擴…

回調函數應用示例

回調函數是一種通過函數指針&#xff08;或引用&#xff09;調用的函數&#xff0c;它在特定事件或條件發生時被另一個函數調用。回調函數的核心思想是將函數作為參數傳遞&#xff0c;以便在適當的時候執行自定義邏輯&#xff0c;常用于異步編程、事件驅動架構等場景。 業務場景…

linux標準庫頭文件解析

linuxc標準庫 C 標準庫&#xff08;C Standard Library&#xff09;包含了一組頭文件&#xff0c;這些頭文件提供了許多函數和宏&#xff0c;用于處理輸入輸出、字符串操作、數學計算、內存管理等常見編程任務。。 頭文件功能簡介<stdio.h>標準輸入輸出庫&#xff0c;包含…

Unbuntu 命令

Ubuntu 命令速查表? ?分類??命令??功能描述??示例/常用選項????文件與目錄?ls列出目錄內容ls -a&#xff08;顯示隱藏文件&#xff09;; ls -lh&#xff08;詳細列表易讀大小&#xff09; cd切換目錄cd ~&#xff08;主目錄&#xff09;; cd ..&#xff08;上級…

怎么在excel單元格1-5行中在原來內容前面加上固定一個字?

環境&#xff1a; WPS 2024 問題描述&#xff1a; 怎么在excel單元格1-5行中在原來內容前面加上固定一個字&#xff1f; 解決方案&#xff1a; 1.在Excel中&#xff0c;如果您想在單元格的內容前面添加一個固定的字&#xff0c;可以通過以下幾種方法實現&#xff1a; 方法…

Linux zip、unzip 壓縮和解壓

zip 命令用于壓縮文件&#xff0c;壓縮后的文件后綴名為 .zip 。 對應的解壓命令是 unzip 。 測試用的目錄結構如下&#xff0c; userzn:~/test$ tree . ├── folder1 │ ├── folder111 │ │ └── file1.txt │ └── main1.c ├── folder2 │ ├── …

【C語言練習】047. 理解遞歸與循環的轉換

047. 理解遞歸與循環的轉換 047. 理解遞歸與循環的轉換1. 遞歸與循環的基本概念遞歸循環2. 遞歸與循環的轉換示例1:計算階乘示例2:漢諾塔問題3. 遞歸與循環的適用場景遞歸:循環:一、遞歸的適用場景與代碼示例1. 分治問題2. 樹形結構遍歷3. 復雜狀態問題二、循環的適用場景與…

我的創作紀念日——《驚變256天》

我的創作紀念日——《驚變256天》 機緣收獲日常成就憧憬 最近&#xff0c;博主收到了 CSDN 發來的系統消息&#xff0c;這才驚覺&#xff0c;自上次第128天創作紀念日之后&#xff0c;竟又悄然走過了 128 天。站在 256 天這個頗具意義的里程碑前回望&#xff0c;博主在2023 年 …

Redis 事務與管道:原理、區別與應用實踐

在現代分布式系統開發中&#xff0c;Redis 作為高性能的內存數據庫&#xff0c;其事務處理和管道技術是開發者必須掌握的核心知識點。本文將深入探討 Redis 事務和管道的實現原理、使用場景、性能差異以及最佳實踐&#xff0c;幫助開發者根據實際需求選擇合適的技術方案。 一、…

Mysql 8.0.32 union all 創建視圖后中文模糊查詢失效

記錄問題,最近在使用union all聚合了三張表的數據,創建視圖作為查詢主表,發現字段值為中文的篩選無法生效.......... sql示例: CREATE OR REPLACE VIEW test_view AS SELECTid,name,location_address AS address,type,"1" AS data_type,COALESCE ( update_time, cr…

Spatial Transformer Layer

我們知道cnn是無法識別到經過縮放和旋轉的圖片的,但是這個spatial transformer這個neutral network是可以做到的,可以被放到cnn里 接下來就是講解一個空間變換層地例子:我們可以看到,layerl就是layerl-1經過平移得到的,其中,我們layerl中的每一個元素,是上一層每一個元素與權重…

spark-standalone

一、定義&#xff1a;Standalone 模式是一種獨立的集群部署模式&#xff0c;自帶完整服務&#xff0c;可單獨部署到一個集群中&#xff0c;無需依賴任何其他資源管理系統。 二、配置步驟 1.和前面一樣拉到hadoop101的/opt/module這個目錄里面。 2.壓縮 3.重命名為spark-sta…

Vim編輯器命令模式操作指南

Vim 的命令模式&#xff08;即 Normal 模式&#xff09;是 Vim 的核心操作模式&#xff0c;用于執行文本編輯、導航、搜索、保存等操作。以下是命令模式下的常用操作總結&#xff1a; 1. 模式切換 進入命令模式&#xff1a;在任何模式下按 Esc 鍵&#xff08;可能需要多次按&a…

網絡體系結構(OSI,TCP/IP)

網絡體系結構 一、設計分層網絡模型 簡化設計&#xff1a;分層將復雜的大系統分解成小模塊&#xff0c;每一層專注處理特定功能模塊化&#xff1a;每一層獨立&#xff0c;便于開發、調試、更新和維護互操作&#xff1a;不同廠家、不同系統之間可以互相兼容&#xff0c;統一標…

經典 算法

算法 算法&#xff08;Algorithm&#xff09;是指解題方案的準確而完整的描述&#xff0c;是一系列解決問題的清晰指令。簡單來說&#xff0c;算法 就是解決一個問題的具體方法和步驟。在計算機科學中&#xff0c;算法是程序設計的核心&#xff0c;它決定了程序如何執 行特定的…

【Spark】-- DAG 和寬窄依賴的核心

目錄 Spark DAG 和寬窄依賴的核心 一、什么是 DAG? 示例:WordCount 程序的 DAG 二、寬依賴與窄依賴 1. 窄依賴 2. 寬依賴 三、DAG 與寬窄依賴的性能優化 1. 減少 Shuffle 操作 2. 合理劃分 Stage 3. 使用緩存機制 四、實際案例分析:同行車判斷 五、總結 Spark D…

C#中UI線程的切換與后臺線程的使用

文章速覽 UI線程切換示例 后臺線程使用示例 兩者對比適用場景Application.Current.Dispatcher.InvokeTask.Factory.StartNew 執行同步性Application.Current.Dispatcher.InvokeTask.Factory.StartNew 一個贊&#xff0c;專屬于你的足跡&#xff01; UI線程切換 在WPF應用程序…

【HTML】個人博客頁面

目錄 頁面視圖?編輯 頁面代碼 解釋&#xff1a; HTML (<body>): 使用了更加語義化的HTML5標簽&#xff0c;例如<header>, <main>, <article>, <footer>。文章列表使用了<article>包裹&#xff0c;結構清晰。添加了分頁導航。使用了Font…

第J1周:ResNet-50算法實戰與解析

&#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客 &#x1f356; 原作者&#xff1a;K同學啊 我的環境 語言環境:Python3.8 編譯器:Jupyter Lab 深度學習環境:Pytorchtorch1.12.1cu113 torchvision0.13.1cu113 一、準備工作 二、導入數據 三、劃分數據…

養生:健康生活的極簡攻略

在追求高效生活的當下&#xff0c;養生也能化繁為簡。通過飲食、運動、睡眠與心態的精準調節&#xff0c;就能輕松為健康續航。 飲食上&#xff0c;遵循 “均衡、節制” 原則。早餐用一杯熱豆漿搭配水煮蛋和半個蘋果&#xff0c;喚醒腸胃活力&#xff1b;午餐以糙米飯為主食&am…