什么是这个宏#define type_string(name){#name,name}

时间:2017-07-16 15:22:40

标签: c string macros

让我们尽可能简单地做第一个例子。

我想知道如何应用这个宏;像这里申请例如printf("%s",macro(arg));

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

#define type_string(name) { #name , name }

int main(void) {

char *hi = "Hello";    
char *arr[]=type_string(hi);
printf("%s\n",type_string(hi));

 return 0;
}

还有什么可以打印函数名称的其他方法: 我的最后一个解决方案就是这个:

是否有更好的方法来优化此代码,例如调整__func__

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>


// let's declare different functions for calculation
int add(int x, int y);
int sub(int x, int y);
int mul(int x, int y);
int divide(int x, int y);

// let's declare function pointers to different behaviors
//int (*functionPtr_1[4])(int,int);                            // basic form
typedef int (*myFuncDef)(int, int);                       // typedef as the basic form
int do_calculations (int (*functionPtr)(int, int));       // function receives function pointer with two args and returns int
int (*functionFactory(int n))(int, int);



int main() {
    int m = 6;
    int n = 10;
    int res,i;

    int (*functionPtr_arr[4])(int,int) = {&add, &sub, &mul, &divide};

    for(i=0;i<4;i++)
    {
        res=(*functionPtr_arr[i])(4,5);
    }
}

int add(int x, int y) {
int result = x + y;
printf("result for %s op is %d\n",__func__,result);
return result;
}

int sub(int x, int y) {
int result = x - y;
printf("result for %s op is %d\n",__func__,result);
return result;
}

int mul(int x, int y) {
int result = x * y;
printf("result for %s op is %d\n",__func__,result);
return result;
}

int divide(int x, int y) {
int result = x / y;
printf("result for %s op is %d\n",__func__,result);
return result;
}

3 个答案:

答案 0 :(得分:3)

#define FN_RECORD(f) { #f, f } 这个宏的工作原理是将变量in,f,并将该值放入它所替换的内容中。

实施例

有一个函数int abc(void);

在预处理后,将FN_RECORD(abc)放入代码中将替换为{ "abc", abc }#创建一个字符串。

创建此宏的人似乎希望将它用作函数的名称作为c-string,以及它的函数指针。

答案 1 :(得分:3)

描述宏的评论非常清楚,因此不确定您可能会对此感到困惑。

在上下文中,它用于为fns数组生成初始化程序。所以:

fn_record fns[3] = {                        
    FN_RECORD(fna),
    FN_RECORD(fnb),
    FN_RECORD(fnc) 
};

扩展为:

fn_record fns[3] = {                        
    {"fna", fna},
    {"fnb", fnb},
    {"fnc", fnc} 
};

评论说这是为了节省你打字,但这是一个相当愚蠢的理由 - 它几乎不值得节省宝贵的时间。它有用的是确保字符串和函数名称匹配以避免可能的错误。

答案 2 :(得分:0)

让我们一步一步地分解它。

#define type_string(name) { #name , name }

int main(void) {
    char *hi = "Hello";    
    char *arr[]=type_string(hi);
    printf("%s\n",type_string(hi));
}

编译分两个阶段进行(三个,如果计算链接,但让我们忽略它)。在很多情况下,预处理器和编译器实际上是独立的程序,但编译器会自动运行预处理器。

预处理

首先,我们进行所有预处理。那么让我们来看看会发生什么:

char *arr[]=type_string(hi);

令牌hi传递给type_stringhi是变量的事实并不重要; name包含hi,而不是"Hello"

  • #是字符串化运算符。由于namehi#name的评估结果为"hi"

  • name只评估为hi

所以type_string(hi)作为一个整体评估为{ "hi" , hi },整个行变为char *arr[]={ "hi" , hi };printf("%s\n", type_string(hi));的工作方式相同,变为printf("%s\n", { "hi" , hi });

编译

现在预处理已经完成,实际的编译器就可以了。这是编译器将看到的内容:

int main(void) {
    char *hi = "Hello";    
    char *arr[]={ "hi" , hi };
    printf("%s\n",{ "hi" , hi });
}

{ "hi", hi }将评估为char*的数组;第一个元素隐式指向(常量)字符串文字"hi",第二个元素初始化为当前包含在hi中的地址,恰好是字符串文字"Hello"的地址

当然,这不起作用; printf("%s\n", { "hi" , hi })期待一个字符串并获取一个数组文字,这在该上下文中是不合法的。

您可以执行printf("%s, %s\n", arr[0], arr[1]);,这将打印hi, Hello