Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 宏如何根据传递给它的类型定义有效的全局名称?_C_Generics_Macros_C11 - Fatal编程技术网

C 宏如何根据传递给它的类型定义有效的全局名称?

C 宏如何根据传递给它的类型定义有效的全局名称?,c,generics,macros,c11,C,Generics,Macros,C11,我相信这个标题是不言自明的,但这里有一个例子来说明我试图实现的目标: #define PASTE2(_0, _1) _0 ## _1 #define DEFINE_OPS_FOR_TYPE(TYPE) \ int PASTE2(do_something_with_, TYPE)(void) { \ /* do_something_with_<TYPE> */ \ } 这正如预期的

我相信这个标题是不言自明的,但这里有一个例子来说明我试图实现的目标:

#define PASTE2(_0, _1)  _0 ## _1

#define DEFINE_OPS_FOR_TYPE(TYPE)                   \
    int PASTE2(do_something_with_, TYPE)(void) {    \
        /* do_something_with_<TYPE> */              \
    }
这正如预期的那样有效,但我对其他可能的解决方案很好奇,即使它们过于复杂。我曾想过使用
\u Generic
,但我看不出它对定义名称有什么帮助


你能想出另一种解决方案吗?

在你想做的符号的声明或定义级别上,没有多少方法可以将事物定义为所讨论类型的唯一标识符<代码>\u通用的或等效的替换太晚了,对预处理器没有用处

但只有有限数量的标准类型会造成这样的问题。因此,您可以很容易地提出一个定义这些类型的约定

其中,
\u Generic
可以提供帮助,它位于这些已定义符号的使用端。在这里,您可以执行以下操作

_Generic((X),
  unsigned long: do_something_with_ulong,
  unsigned char: do_something with_uchar,
  ...
)(X)

在本文中,我遵循这个方案,您会发现很多支持宏已经就位。

我最终使用了一个带有空参数的宏。例如:

#define STR2(x)             # x
#define STR(x)              STR2(x)
#define PASTE3(_1,_2,_3)    _1 ## _2 ## _3
#define FOO(_1,_2,_3)       PASTE3(_1, _2, _3)

printf("%s\n", STR(FOO(int,,)));
printf("%s\n", STR(FOO(unsigned, int,)));
printf("%s\n", STR(FOO(unsigned, long, long)));
如您所能,输出为:

int
unsignedint
unsignedlonglong
我不记得根据标准使用空宏参数是否定义得很好,但我可以告诉您,Clang 3.1不会对
-std=c11
-pedantic
发出任何警告

如果您想尝试,下面是一些代码:

#include <stdio.h>
#include <limits.h>

#define PASTE4(_1,_2,_3,_4) _1 ## _2 ## _3 ## _4

#define DEFINE_OPS_FOR_TYPE1(T1)        DEFINE_OPS_FOR_TYPE2(T1,)
#define DEFINE_OPS_FOR_TYPE2(T1, T2)    DEFINE_OPS_FOR_TYPE3(T1,T2,)
#define DEFINE_OPS_FOR_TYPE3(T1, T2, T3)                                    \
    int PASTE4(write_,T1,T2,T3)(FILE *file, void *data) {                   \
        T1 T2 T3 foo;                                                       \
        int written = fprintf(file, fmt_specifier(foo), *((T1 T2 T3 *)data));\
        return written > 0 ? 0 : -1;                                        \
    }

#define fmt_specifier(x)                \
    _Generic((x),                       \
        int: "%i",                      \
        unsigned int: "%u",             \
        unsigned long long: "%llu",     \
        default: NULL                   \
    )

DEFINE_OPS_FOR_TYPE1(int)
DEFINE_OPS_FOR_TYPE2(unsigned, int)
DEFINE_OPS_FOR_TYPE3(unsigned, long, long)

int main() {
    int var_int = INT_MAX;
    write_int(stdout, &var_int);
    printf("\n");
    unsigned int var_uint = UINT_MAX;
    write_unsignedint(stdout, &var_uint);
    printf("\n");
    unsigned long long var_ullong = ULLONG_MAX;
    write_unsignedlonglong(stdout, &var_ullong);
    printf("\n");
    return 0
}
#包括
#包括
#定义粘贴4(_1,_2,_3,_4)_1##########u 4
#定义类型1(T1)的操作定义类型2(T1)的操作
#定义类型2(T1,T2)的操作定义类型3(T1,T2,)的操作
#为类型3(T1、T2、T3)定义操作\
intpaste4(write,T1,T2,T3)(文件*文件,无效*数据){\
T1 t2t3foo\
int write=fprintf(文件,fmt_说明符(foo),*((T1 T2 T3*)数据)\
返回写入>0?0:-1\
}
#定义fmt_说明符(x)\
_通用((x)\
int:“%i”\
无符号整数:“%u”\
未签名的长:“%llu”\
默认值:NULL\
)
为类型1(int)定义操作
为类型2定义操作(无符号,整数)
为类型3(无符号、长、长)定义操作
int main(){
int var_int=int_MAX;
写入(标准输出和变量输入);
printf(“\n”);
无符号整数var_uint=uint_MAX;
无符号写入(标准输出和变量输入);
printf(“\n”);
无符号long long var_ullong=ullong_MAX;
写入未签名的longlong(stdout和var_llong);
printf(“\n”);
返回0
}

我不知道C11,但在此之前,宏肯定没有能力进行复杂的字符串处理(例如,替换空格或“*”)之类的字符。@OliCharlesworth您认为可变宏是否适用于
为类型(unsigned,int)定义操作
为类型(unsinged,long,long)定义操作
?我正在考虑为类型(…)定义操作,并为最多3个参数标记粘贴所有的变量。但我怀疑这是可能的。空参数确实定义得很好,没有问题that@JensGustedt:太好了!感谢您的输入。您可以使用一些技巧来改进这一点,例如VA_NARGS,这是一种计算宏中参数数量的常用方法。@Morwenn:谢谢您的提示。上面的代码只是一个演示。我剪了很多线来适应这里。真正的一个使用了一个更简单的变体
PP_NARG
——对他和他的赞誉。
#include <stdio.h>
#include <limits.h>

#define PASTE4(_1,_2,_3,_4) _1 ## _2 ## _3 ## _4

#define DEFINE_OPS_FOR_TYPE1(T1)        DEFINE_OPS_FOR_TYPE2(T1,)
#define DEFINE_OPS_FOR_TYPE2(T1, T2)    DEFINE_OPS_FOR_TYPE3(T1,T2,)
#define DEFINE_OPS_FOR_TYPE3(T1, T2, T3)                                    \
    int PASTE4(write_,T1,T2,T3)(FILE *file, void *data) {                   \
        T1 T2 T3 foo;                                                       \
        int written = fprintf(file, fmt_specifier(foo), *((T1 T2 T3 *)data));\
        return written > 0 ? 0 : -1;                                        \
    }

#define fmt_specifier(x)                \
    _Generic((x),                       \
        int: "%i",                      \
        unsigned int: "%u",             \
        unsigned long long: "%llu",     \
        default: NULL                   \
    )

DEFINE_OPS_FOR_TYPE1(int)
DEFINE_OPS_FOR_TYPE2(unsigned, int)
DEFINE_OPS_FOR_TYPE3(unsigned, long, long)

int main() {
    int var_int = INT_MAX;
    write_int(stdout, &var_int);
    printf("\n");
    unsigned int var_uint = UINT_MAX;
    write_unsignedint(stdout, &var_uint);
    printf("\n");
    unsigned long long var_ullong = ULLONG_MAX;
    write_unsignedlonglong(stdout, &var_ullong);
    printf("\n");
    return 0
}