Linux C - .h、巨集

 


基本定義

定義數字及用法

#define N 10
char str[N];


定義字串及用法

#define STRING "String"
char *str = STRING;


定義結構及用法

struct my_struct {
int type;
char buf[32];
};
struct my_struct myStruct;
myStruct.type = 1;
strcpy(myStruct.buf, "string");

宣告可以寫成

typedef struct my_struct {
int type;
char buf[32];
} MY_STRUCT;
MY_STRUCT myStruct;


定義連續數字(預設數值從0開始)

enum {
NUMBER_ONE,
NUMBER_TWO
};

指定數值

enum {
NUMBER_ONE = 0x1,
NUMBER_TWO = 0x4
};



extern 的用法

可以讓所有 .c 都能使用 value,而且是使用同一個位址的變數。

在 main.c 的全域定義

    int value = 0;

其他 .c 的全域改定義成

    extern int value;



weak 的用法

可以讓所有 .c 都能使用 value,而且是使用同一個位址的變數。
能在 .h 定義,compile可以過,也不會衝突。

    __attribute__((weak)) int value;



條件編譯

參數定義

#define AAA 1
#define BBB 1

或在 Makefile 中,定義成
CFLAGS += -DAAA=1 -DBBB

判斷方法一

#ifdef AAA
#endif

判斷方法二

#if defined(AAA) && !defined(BBB)
#endif

判斷方法三

#if AAA
#elif BBB
#else
#endif

AAA 與 BBB 也可以直接用  0 或 1 取代


中止編譯


#if AAA
#error "Unsupported"
#endif



巨集

一般寫法:

    scanf("%10c", str);

巨集改寫:

#define FMT(x) ("%"NUM(x)"c")
#define NUM(x) #x
scanf(FMT(N), str);


用##分開變數,以下兩種定義的執行結果都為 1234

#define debug(a, b) fprintf(stderr, "%d%d\n", a, b);
#define debug(a, b) fprintf(stderr, "%d\n", a##b);
debug(12, 34);

=== 執行結果 ===
1234


預先定義的:

__FILE__:檔名
__LINE__:所在行數
__FUNCTION__funcion名稱
__DATE__:編譯日期
__TIME__:編譯時間



巨集定義別名

.h 定義

#define REGISTER(func) func##_register()
#define UNREGISTER(func, data) func##_unregister(data)

.c 呼叫

REGISTER(abc) // 會改呼叫 abc_register()
REGISTER(abc, dataValue) // 會改呼叫 abc_unregister(dataValue)



巨集定義 args 

.h 範例:

#define DEBUG_FILE "/tmp/debug.log"
#define DEBUG_LOG(toFile, args...) debug_log(toFile, __FUNCTION__, __LINE__, ##args)

.c 範例:

void debug_log(int toFile, const char *function, int line, const char *fmt, ...)
{
char *buffer = NULL;
FILE *fp = NULL;
va_list ap;

va_start(ap, fmt);

if (vasprintf(&buffer, fmt, ap) >= 0) {
if (toFile && (access(DEBUG_FILE, F_OK) == 0) && (fp = fopen(DEBUG_FILE, "a+"))) {
fprintf(fp, "P%d,T%lu[%s:%d] %s\n", getpid(), time(0), function, line, buffer);
fclose(fp);
}
printf("%s", buffer);

free(buffer);
va_end(ap);
}
}


方法二:

int main(int argc, char **argv) {
#define debug(fmt, ...) { \
fprintf(stderr, "(%s:%s:%d) "fmt"\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
}
debug("%s %d", "message", 1);
}

=== 執行結果 ===
(test.c:main:9) message 1



 func 傳入 func

當你呼叫的 func 要傳入一個 func 做為參數,定義及用法

void func(char * (*func_in)(char *)) {
printf("%s\n", func_in("message\n"));
}
char *func_print(char *msg) {
printf("%s", msg);
return "ok";
}
int main(int argc, char **argv) {
func(func_print);
}

=== 執行結果 ===
message
ok

註:如果 func_print 不需要回傳值,定義改成  void func(void (*func_in)(char *))  即可


在結構內使用 func 定義

.h 定義:

struct func_structural {
char * (*func_a)(char *);
int (*func_b)(void *, int);
}

.c 使用:

struct func_structural myStruct;
myStruct.func_a = func_print;

















沒有留言:

張貼留言