首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C++ 常量全解析:數值/字符/字符串/符號常量的類型、存儲與應用陷阱

     編輯:關於C語言

常量是 C++ 程序中不可變的數據實體,正確理解其類型推導、內存佈局與隱式轉換規則,對編寫健壯、高效的代碼至關重要。本文系統梳理四大常量類別,揭示編譯器背後的類型判斷邏輯與常見陷阱。

一、數值常量:從字面量到類型推導

1. 整型常量的類型判斷規則

C++ 根據數值範圍與後綴自動推導類型:

數值範圍無後綴類型L/l 後綴U/u 後綴UL/ul 後綴
-32768 ~ 32767intlongunsigned intunsigned long
-2147483648 ~ 2147483647longlongunsigned longunsigned long
超過長整型範圍long long (C++11)long longunsigned long longunsigned long long
關鍵點:十進制無符號常量不存在,但非負整數可隱式轉換給 unsigned 變量。123U 強制為 unsigned int,123LL 強制為 long long (C++11)。

2. 進制表示法

int dec = 1357;      // 十進制
int oct = 020;       // 八進制 (0 開頭) = 16 十進制
int hex = 0x20;      // 十六進制 (0x/0X 開頭) = 32 十進制
int bin = 0b1010;    // 二進制 (C++14, 0b/0B 開頭) = 10 十進制

3. 浮點常量的精度與後綴

形式示例默認類型F/f 後綴L/l 後綴
十進制小數3.14, .5, 5.doublefloatlong double
指數形式3.14e0, .314e1, 31.4e-1doublefloatlong double

內存存儲:無論源碼寫成何種形式,編譯器均按 IEEE 754 標準化指數形式 存儲(符號位+指數位+尾數位)。VC6.0 下 double 與 long double 均佔 8 字節,GCC 下 long double 佔 12/16 字節。

二、字符常量:ASCII 編碼與轉義機制

1. 基本字符常量

  • 單引號包裹單字符:'a', 'Z', '#'
  • 佔 1 字節,存儲 ASCII 碼值 (如 'A' = 65)
  • 區分大小寫:'a' (97) ≠ 'A' (65)

2. 轉義字符完整表

轉義序列含義ASCII 碼
\n換行 (LF)10
\r回車 (CR)13
\t水平製表9
\v垂直製表11
\b退格8
\f換頁12
\\反斜杠92
\'單引號39
\"雙引號34
\?問號 (避免三字母組)63
\0空字符 (字符串結束符)0
\ooo八進制 (1-3位)-
\xhh十六進制 (1-2位)-

3. 字符與整數互轉實戰

char c = 'A';      // 存儲 65
int i = c;         // 隱式轉換:i = 65
char c2 = i + 32;  // 'a' (97) - 大小寫轉換技巧
printf("%c %d\n", c2, c2);  // 輸出: a 97
陷阱:char 是否有符號由實現定義!有符號時範圍 -128~127,無符號 0~255。跨平台代碼應顯式使用 signed char/unsigned char 或 uint8_t/int8_t。

三、字符串常量:存儲佈局與特殊操作

1. 內存結構

"abc"  // 佔 4 字節:'a' 'b' 'c' '\0'
        // 編譯器自動在末尾添加 '\0' (不計入字符串長度)
sizeof("abc") == 4
strlen("abc") == 3

2. 字符常量 vs 字符串常量

形式類型大小示例
'a'char1 字節單字符
"a"const char[2]2 字節'a' + '\0'

3. 續行與嵌入引號

// 反斜杠續行 (行尾不能有空格)
cout << "We must study C\
++ hard!";  // 輸出: We must study C++ hard!

// 嵌入雙引號
cout << "I say \"Thank you!\"\n";  // 輸出: I say "Thank you!"

// 雙反斜杠輸出單反斜杠
cout << "abc\\n";  // 輸出: abc\n (5字符: a b c \ n)

四、符號常量:#define 與 const 的對決

1. 宏定義常量

#define PRICE 30
#define PI 3.141592653589793

// 預處理階段文本替換,無類型檢查,不佔運行時內存
// 優點:一改全改,無運行開銷
// 缺點:無作用域,調試不可見,類型不安全

2. const 修飾的變量 (現代 C++ 首選)

const double PI = 3.141592653589793;
constexpr int MAX_SIZE = 1024;  // C++11 編譯期常量

// 優點:有類型、有作用域、可調試、支持類型檢查
// constexpr 保證編譯期計算,可用於數組大小、模板參數

3. 兩者對比總結

維度#defineconst/constexpr
處理階段預處理編譯
類型安全無有
作用域文件級 (無)塊/命名空間級
調試可見性不可見可見
內存佔用無 (文本替換)可能佔用 (非 constexpr)
指針/引用不能取地址可取地址

五、常見陷阱與最佳實踐

陷阱 1:整數字面量溢出

int a = 2147483648;  // 錯誤:超過 int 範圍
long b = 2147483648L; // 正確:長整型後綴
auto c = 2147483648;  // C++11 自動推導為 long/long long

陷阱 2:浮點精度比較

// 錯誤
if (x == 0.1) ...

// 正確:使用 epsilon 比較
const double EPS = 1e-9;
if (fabs(x - 0.1) < EPS) ...

陷阱 3:字符串字面量修改導致未定義行為

char *p = "hello";  // 危險:指向只讀內存區
p[0] = 'H';         // UB:運行時崩潰

// 正確
const char *p = "hello";  // 或 char arr[] = "hello";

最佳實踐清單

  1. 優先使用 constexpr (編譯期常量) 和 const (運行期只讀)
  2. 魔數全部賦予語義名稱:const int MAX_CONNECTIONS = 100;
  3. 相關常量組織為 enum class 或 namespace
  4. 跨文件共享常量:頭文件 extern const int VAL;,源文件定義
  5. 避免在頭文件定義非 constexpr/inline 變量 (C++17)

總結

C++ 常量體系涵蓋 數值 (整數/浮點/進制/後綴)、字符 (ASCII/轉義/整數互轉)、字符串 (結束符/續行/嵌入)、符號 (宏/const/constexpr) 四大類。深度理解類型推導規則、內存佈局、隱式轉換陷阱,配合現代 C++ (constexpr, enum class, inline) 最佳實踐,能顯著提升代碼的可讀性、安全性與性能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved