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

C 標準庫參考指南:stddef.h 核心類型與宏詳解 (offsetof、size_t、ptrdiff_t、NULL、wchar_t)

     編輯:關於C語言

stddef.h 概覽

<stddef.h> 定義 C 標準庫通用的基礎類型與宏,眾多頭文件會重複包含它。核心內容:

  • 3 個基本類型:size_t、ptrdiff_t、wchar_t
  • 1 個宏常量:NULL
  • 1 個宏函數:offsetof

類型詳細定義

size_t - 無符號整數類型

  • 用於表示對象大小 (位元組數)
  • sizeof 運算符返回類型
  • 數組索引、循環計數器首選類型
  • 32 位系統通常 32 位,64 位系統 64 位
  • 格式化輸出:%zu (C99)

ptrdiff_t - 有符號整數類型

  • 兩個指針相減的結果類型
  • 表示內存地址差 (元素個數而非位元組)
  • 可為負 (指針順序相反)
  • 格式化輸出:%td (C99)

wchar_t - 寬字符類型

  • 表示擴展字符集 (Unicode 等)
  • 大小實現定義 (通常 16 或 32 位)
  • 寬字符字面量:L'x'、寬字符串:L"hello"
  • 配合 <wchar.h> 使用寬字符串函數

NULL - 空指針常量

  • 定義為 ((void*)0) 或 0 或 0L
  • 用於指針初始化、判空、函數返回失敗標誌
  • C++ 建議用 nullptr 替代

offsetof 宏:結構體成員偏移量計算


size_t offsetof(type, member-designator);
  • 返回結構體 type 中成員 member 相對結構體起始地址的位元組偏移
  • 編譯期常量表達式,可用於靜態斷言、數組大小
  • 實現原理:((size_t)&(((type *)0)->member)) (利用空指針解引用計算偏移,未定義行為但編譯器內置支持)

實戰示例


#include <stddef.h>
#include <stdio.h>

struct User {
    char name[50];
    char alias[50];
    int level;
    double score;
    struct User *next;
};

int main() {
    printf("size_t 大小: %zu 位元組\n", sizeof(size_t));
    printf("ptrdiff_t 大小: %zu 位元組\n", sizeof(ptrdiff_t));
    printf("wchar_t 大小: %zu 位元組\n", sizeof(wchar_t));
    
    printf("\n結構體 User 佈局:\n");
    printf("總大小: %zu\n", sizeof(struct User));
    printf("name 偏移: %zu\n", offsetof(struct User, name));
    printf("alias 偏移: %zu\n", offsetof(struct User, alias));
    printf("level 偏移: %zu\n", offsetof(struct User, level));
    printf("score 偏移: %zu\n", offsetof(struct User, score));
    printf("next 偏移: %zu\n", offsetof(struct User, next));
    
    // 驗證對齊
    struct User u;
    printf("\n實際地址驗證:\n");
    printf("&u = %p\n", (void*)&u);
    printf("&u.level = %p (偏移 %td)\n", (void*)&u.level, (char*)&u.level - (char*)&u);
    
    return 0;
}

典型輸出 (64 位系統)

size_t 大小: 8 位元組
ptrdiff_t 大小: 8 位元組
wchar_t 大小: 4 位元組

結構體 User 佈局:
總大小: 120
name 偏移: 0
alias 偏移: 50
level 偏移: 100
score 偏移: 104
next 偏移: 112

實際地址驗證:
&u = 0x7ffc12345670
&u.level = 0x7ffc123456d4 (偏移 100)

注意:double 8 位元組對齊,導致 level (4 位元組) 後有 4 位元組填充,score 從 104 開始。

進階應用場景

1. 容器宏 (類似 Linux kernel container_of)


#define container_of(ptr, type, member) \
    ((type *)((char *)(ptr) - offsetof(type, member)))

// 用法: 從鏈表節點指針獲取包含結構體指針
struct ListNode { struct ListNode *next; };
struct MyStruct { int data; struct ListNode node; };

struct ListNode *node_ptr = ...;
struct MyStruct *obj = container_of(node_ptr, struct MyStruct, node);

2. 靜態斷言檢查結構佈局


#include <assert.h>

// C11 _Static_assert
_Static_assert(offsetof(struct User, level) == 100, "level 偏移量變更");
_Static_assert(sizeof(struct User) == 120, "結構體大小變更");

3. 序列化/反序列化偏移計算


void serialize_user(const struct User *u, unsigned char *buf) {
    memcpy(buf + offsetof(struct User, name), u->name, 50);
    memcpy(buf + offsetof(struct User, alias), u->alias, 50);
    memcpy(buf + offsetof(struct User, level), &u->level, sizeof(int));
    // ...
}

跨平台注意事項

項目32 位系統64 位系統
size_t / ptrdiff_t4 位元組8 位元組
指針大小48
結構體對齊通常 4/8通常 8/16
wchar_t2 或 4通常 4

代碼中不要假設具體大小,始終使用 sizeof 和 offsetof。

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