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

C語言指標長度與類型完整解析:可移植性、預定義類型與指標運算

     編輯:關於C語言

指標長度基礎認知

現代平台:資料指標長度通常一致(32 位元系統 4 bytes、64 位元系統 8 bytes),與指向型態無關。
C 標準:不保證所有型態指標長度相同,但實務上幾乎一致。
函數指標:長度可能不同於資料指標(如 Harvard 架構、分段記憶體模型)。

指標長度測試程式


#include 
#include 

struct p { int n; float f; };

int main() {
    struct p *sptr;
    printf("sizeof *char: %zu\n", sizeof(char*));
    printf("sizeof *int: %zu\n", sizeof(int*));
    printf("sizeof *float: %zu\n", sizeof(float*));
    printf("sizeof *double: %zu\n", sizeof(double*));
    printf("sizeof *struct: %zu\n", sizeof(sptr));
    return 0;
}

典型 64 位元輸出:全部為 8(bytes)
典型 32 位元輸出:全部為 4(bytes)

指標相關預定義類型

size_t 類型深度解析

本質:機器相關的無號整數型別,大小足以表示記憶體中最大物件位元組數。
32 位元系統:4 bytes(unsigned int)
64 位元系統:8 bytes(unsigned long)

核心用途

  • sizeof 運算子返回型別
  • 記憶體分配函數參數:malloc(size_t)
  • 字串長度:strlen 返回 size_t
  • 陣列索引、迴圈計數器、指標運算

列印格式陷阱

size_t 為無號型別,列印需用正確格式:

  • 推薦:%zu (C99)
  • 相容:%lu (配合 unsigned long 轉型)、%u (32 位元)
  • 錯誤:%d、%ld — 可能導致負數顯示或截斷

範例


size_t s = sizeof(double);
printf("Size: %zu\n", s);  // 正確

ptrdiff_t 類型深度解析

本質:有號整數型別,用於儲存同一陣列中兩指標相減的結果。
與 size_t 差異:size_t 為無號(長度非負),ptrdiff_t 為有號(差值可負)。

範例:計算字串長度


#include 
#include 
#include 

int main() {
    char str[] = "Hello world!";
    char *pstart = str;
    char *pend = str + strlen(str);
    ptrdiff_t diff = pend - pstart;
    printf("Length: %td\n", diff);  // %td 為 ptrdiff_t 格式 (C99)
    return 0;
}

intptr_t / uintptr_t:指標與整數互轉

用途:將指標位址儲存為整數,進行整數運算後轉回指標。
保證:(void*)(uintptr_t)ptr == ptr(往返轉換保值)。

應用場景

  • 指標標記(利用低位元組對齊位存狀態)
  • 指標哈希、比較、儲存於整數容器
  • 與硬體介面交互(暫存器映射)
  • 偵錯器、序列化工具處理指標值

範例:指標標記


#include 

void *ptr = malloc(100);
// 利用對齊特性(假設 8 位元組對齊,低 3 位為 0)
uintptr_t marked = (uintptr_t)ptr | 1;  // 設標記位
// 使用時清除標記
void *original = (void*)(marked & ~1);

指標運算規則

  1. 指標 + 整數:按指向型態大小縮放,ptr + n 移動 n * sizeof(*ptr) 位元組
  2. 指標 - 指標:同一陣列內,返回元素個數差(ptrdiff_t)
  3. 指標比較:同一陣列/物件內比較位址大小
  4. 指標 - 整數:反向移動
  5. 禁止:指標 + 指標、指標 * 整數、指標 / 整數、指標 % 整數

可移植性最佳實踐

  1. 使用 size_t 表示大小、索引、計數
  2. 指標差值用 ptrdiff_t
  3. 指標轉整數用 uintptr_t/intptr_t
  4. 避免假設指標長度(sizeof(void*) == sizeof(int) 在 64 位元錯誤)
  5. 避免指標與 int/long 直接轉換,用標準類型
  6. printf 格式:%p 印指標、%zu 印 size_t、%td 印 ptrdiff_t

總結

  • 資料指標長度通常與平台位元數一致(32/64 bits),函數指標可能不同
  • size_t:大小/索引/計數首選,無號,%zu
  • ptrdiff_t:指標差值,有號,%td
  • intptr_t/uintptr_t:指標↔整數安全轉換
  • 善用標準類型而非假設長度,編寫可移植 32/64 位元程式碼
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
類型定義於用途特性
size_tstddef.h物件大小、陣列索引、迴圈計數無號,足以容納最大物件大小
ptrdiff_tstddef.h指標差值(指標減法結果)有號,可表示負差值
intptr_tstdint.h (C99)儲存指標位址(整數形式)有號,足以容納指標
uintptr_tstdint.h (C99)儲存指標位址(無號形式)無號,足以容納指標