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

C語言模擬默認參數:宏技巧、重載模擬與實戰方案

     編輯:C 語言入門

C 語言無原生默認參數

C++ 支援 void f(int a = 10);,C 必須通過宏、結構體、_Generic (C11) 或設計模式變通。

方案一:宏重定向(最常用)

#include <stdio.h>

int _func(int a, int b) { return a + b; }

// 宏展開:f1() → _func(0, 1) ; f1(2) → _func(2, 1)
#define f1(arg0) _func(DEFARG(arg0, 0), 1)

// 萬能宏:參數為空則用默認值
#define DEFARG(name, defval) ((#name[0]) ? (name) : (defval))

int main(void) {
    printf("%d\n", f1());      // 0+1=1
    printf("%d\n", f1(5));    // 5+1=6
    return 0;
}

原理:#name 字符串化,name[0] 判斷是否為空 token。

方案二:結構體 + 指定初始化器 (C99)

typedef struct { int a; int b; } Args;

int func_impl(Args args) { return args.a + args.b; }

#define func(...) func_impl((Args){ .a = 0, .b = 1, __VA_ARGS__ })

int main(void) {
    printf("%d\n", func());          // 1
    printf("%d\n", func(.a=5));     // 6
    printf("%d\n", func(.b=3));     // 3
    printf("%d\n", func(.a=2,.b=4)); // 6
    return 0;
}

優勢:類型安全、參數順序無關、可擴展多參數。

方案三:_Generic 選擇不同實現 (C11)


#define func(...) _Generic((__VA_ARGS__), \
    int: func_int, \
    default: func_default \
)(__VA_ARGS__)

較複雜,適用於嚴格類型分發場景。

方案四:頭文件聲明分離(工程實踐)

// api.h
void _getStr(const char *filename);
#define getStr() _getStr("default.txt")

// api.c
void _getStr(const char *filename) { /* ... */ }

// main.c
#include "api.h"
int main() { getStr(); getStr("custom.txt"); }

編譯單元分離,二進制兼容,適合庫開發。

方案對比總結

方案標準要求類型安全可讀性適用場景
宏重定向C89弱中簡單 1-2 參數
結構體初始化器C99強高多參數、現代代碼庫
_GenericC11強低類型分發、泛型模擬
內部函數+宏C89中高庫接口、二進制兼容

避坑指南

  • 宏參數為空時 __VA_ARGS__ 行為在 C99/C11/GCC/Clang/MSVC 間有差異,C23 標準化了 __VA_OPT__。
  • 結構體方案需注意指定初始化器為 C99 特性,MSVC 早期版本不支援。
  • 宏方案中 #name 字符串化會保留空白,需配合 #name[0] 判斷非空。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved