在C或c++中使用逗号作为宏名

时间:2022-11-25 10:02:08

I'd like to do something like:

我想做的是:

#define , 
#define MAX 10,000,000
// ...
#undef ,

is there any trick to do so?

有什么诀窍吗?

EDIT: I know about the ' digit separator in C++14. I'm looking for a trick to do the same for uncompliant compilers.
EDIT2: Please consider Variadic Macros.

编辑:我知道c++ 14中的数字分隔符。我正在寻找一个技巧来为不兼容的编译器做同样的事情。请考虑可变宏。

6 个解决方案

#1


5  

Warning, black magic ahead.

警告,黑魔法。

Macros can indeed be used, albeit with a preset number of arguments. This number can be arbitrary, but each must be written by hand:

实际上可以使用宏,尽管参数是预先设置的。这个数字可以是任意的,但每一个都必须手写:

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

#define MERGE_EXPAND( a , b )     a##b
#define MERGE( a , b )            MERGE_EXPAND( a , b )

#define COUNT_PICK( a , b , c , pick , ... )  pick

#define COUNT( ... )    COUNT_PICK( __VA_ARGS__ , 3 , 2 , 1 , 0 )

#define JOIN_1( a )           a
#define JOIN_2( a , b )       a##b
#define JOIN_3( a , b , c )   a##b##c

#define JOIN( ... ) MERGE( JOIN_ , COUNT( __VA_ARGS__ ) )( __VA_ARGS__ )

int main( void )
{
    printf( "%d\n" , JOIN( 12345 ) ) ;
    printf( "%d\n" , JOIN( 100,44 ) ) ;
    printf( "%d\n" , JOIN( -10,44,9999 ) ) ;  

    return EXIT_SUCCESS ;
}

The macro COUNT count the number of arguments passed to it. This is done by passing arguments to the helper macro COUNT_PICK, and adding additional argument which are consecutive numbers in reverse order. The number of original arguments passed to COUNT then manipulates the arguments of COUNT_PICK, so that one of the numbers is chosen.

宏计数计算传递给它的参数的数量。这是通过向helper宏COUNT_PICK传递参数来实现的,并添加额外的参数,这些参数是按照相反顺序的连续数字。传递给COUNT的原始参数的数量,然后操作COUNT_PICK的参数,以便选择其中一个数字。

That chosen number is then merged wtih JOIN, resulting in either JOIN_1, JOIN_2, or JOIN_3. The chosen macro is then used with original arguments and simply merges them into a single integer literal.

然后将所选的数字合并为wtih JOIN,从而得到JOIN_1、JOIN_2或JOIN_3。然后,选择的宏与原始参数一起使用,并简单地将它们合并为一个整数值。

This example can be expanded by manually defining more JOIN_X macros where X is a consecutive number. Simultaneously the macros COUNT and COUNT_PICK, must be altered as well.

这个例子可以通过手动定义更多的JOIN_X宏来扩展,其中X是一个连续的数字。同时,还必须修改宏计数和COUNT_PICK。

As an additional benefit, passing invalid arguments, like:

作为附加的好处,传递无效的参数,如:

JOIN( 10,+44 );
JOIN( 10,-44 );
JOIN( 10,*44 );
JOIN( 10,/44 );
JOIN( /10,44 );
//etc...

will yield a compile time warning, but still allows for arguments that will result in a valid integer constant.

将产生编译时警告,但仍然允许产生有效整数常数的参数。

To be used with a Microsoft compiler, tested with SVC14 (Microsoft Visual Studio 2015 Update 3), the code must be amended. Macros COUNT_PICK and MERGE must be wrapped with an additional expand macro:

要与Microsoft编译器一起使用,使用SVC14测试(Microsoft Visual Studio 2015更新3),代码必须修改。宏COUNT_PICK和MERGE必须用一个额外的展开宏包装:

#define EXPAND(...)   __VA_ARGS__

#2


5  

is there any trick to do so?

有什么诀窍吗?

No you can't. Macros have a specific set of characters that can be used to name them (see details here please). , isn't one of them.

不,你不能。宏有一组可以用来命名它们的特定字符(请参阅这里的详细信息)。,不是其中之一。

#3


4  

Go shopping for the latest C++14 compliant compiler. That allows you to use ' as a thousands separator:

购买最新的c++ 14兼容编译器。这样你就可以使用“作为千位分隔符:

#define MAX 10'000'000

#定义MAX 000‘000’

although using a macro in such a brand spanking new C++ compiler is an anachronism.

尽管在这种全新的c++编译器中使用宏是不合时宜的。

Writing 10,000,000 would not end well. If used in an expression then , will stand in for the comma operator.

写1000万不会有好结果。如果在表达式中使用,则表示逗号运算符。

So int a = (10,000,000) would be zero. It could be worse than that: a leading zero denotes an octal literal, so int a = (10,000,010) would actually be 8.

所以int a =(10,000,000) = 0。更糟糕的是:前导0表示八进制,所以int a =(10,000,010)实际上是8。

#4


2  

Sort of, although it's a bit tedious and inelegant:

虽然有点乏味不雅

#define constant(a) (a)
#define constant2(a,b) (a##b)
#define constant3(a,b,c) (a##b##c)

constant(10000)
constant2(10,000)
constant3(10,000,000)

#5


1  

You can always use a custom function that will parse a string literal:

您总是可以使用一个自定义函数来解析字符串文字:

int value = Number( "100,000,000" );

The downsite is the some small overhead for parsing, and the benefits are error checking, and the ability to use any format you want.

下站点是解析的一些小开销,其好处是错误检查,以及使用任何您想要的格式的能力。

The parsing itself can be minimized by reusing const varibles in outer most scopes.

解析本身可以通过在大多数外部作用域中重用const变量来最小化。

#6


1  

One trick to enhance code clarity is to define macro as:

提高代码清晰度的一个技巧是将宏定义为:

#define MAX    (10 * 1000 * 1000)

The rationale is that modern compilers are smart enough to simplify the expression into single integer constant 10000000. This is known as constant propagation (or constant folding).

基本原理是,现代编译器足够聪明,可以将表达式简化为单个整数常量10000000。这被称为常数传播(或常数折叠)。

#1


5  

Warning, black magic ahead.

警告,黑魔法。

Macros can indeed be used, albeit with a preset number of arguments. This number can be arbitrary, but each must be written by hand:

实际上可以使用宏,尽管参数是预先设置的。这个数字可以是任意的,但每一个都必须手写:

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

#define MERGE_EXPAND( a , b )     a##b
#define MERGE( a , b )            MERGE_EXPAND( a , b )

#define COUNT_PICK( a , b , c , pick , ... )  pick

#define COUNT( ... )    COUNT_PICK( __VA_ARGS__ , 3 , 2 , 1 , 0 )

#define JOIN_1( a )           a
#define JOIN_2( a , b )       a##b
#define JOIN_3( a , b , c )   a##b##c

#define JOIN( ... ) MERGE( JOIN_ , COUNT( __VA_ARGS__ ) )( __VA_ARGS__ )

int main( void )
{
    printf( "%d\n" , JOIN( 12345 ) ) ;
    printf( "%d\n" , JOIN( 100,44 ) ) ;
    printf( "%d\n" , JOIN( -10,44,9999 ) ) ;  

    return EXIT_SUCCESS ;
}

The macro COUNT count the number of arguments passed to it. This is done by passing arguments to the helper macro COUNT_PICK, and adding additional argument which are consecutive numbers in reverse order. The number of original arguments passed to COUNT then manipulates the arguments of COUNT_PICK, so that one of the numbers is chosen.

宏计数计算传递给它的参数的数量。这是通过向helper宏COUNT_PICK传递参数来实现的,并添加额外的参数,这些参数是按照相反顺序的连续数字。传递给COUNT的原始参数的数量,然后操作COUNT_PICK的参数,以便选择其中一个数字。

That chosen number is then merged wtih JOIN, resulting in either JOIN_1, JOIN_2, or JOIN_3. The chosen macro is then used with original arguments and simply merges them into a single integer literal.

然后将所选的数字合并为wtih JOIN,从而得到JOIN_1、JOIN_2或JOIN_3。然后,选择的宏与原始参数一起使用,并简单地将它们合并为一个整数值。

This example can be expanded by manually defining more JOIN_X macros where X is a consecutive number. Simultaneously the macros COUNT and COUNT_PICK, must be altered as well.

这个例子可以通过手动定义更多的JOIN_X宏来扩展,其中X是一个连续的数字。同时,还必须修改宏计数和COUNT_PICK。

As an additional benefit, passing invalid arguments, like:

作为附加的好处,传递无效的参数,如:

JOIN( 10,+44 );
JOIN( 10,-44 );
JOIN( 10,*44 );
JOIN( 10,/44 );
JOIN( /10,44 );
//etc...

will yield a compile time warning, but still allows for arguments that will result in a valid integer constant.

将产生编译时警告,但仍然允许产生有效整数常数的参数。

To be used with a Microsoft compiler, tested with SVC14 (Microsoft Visual Studio 2015 Update 3), the code must be amended. Macros COUNT_PICK and MERGE must be wrapped with an additional expand macro:

要与Microsoft编译器一起使用,使用SVC14测试(Microsoft Visual Studio 2015更新3),代码必须修改。宏COUNT_PICK和MERGE必须用一个额外的展开宏包装:

#define EXPAND(...)   __VA_ARGS__

#2


5  

is there any trick to do so?

有什么诀窍吗?

No you can't. Macros have a specific set of characters that can be used to name them (see details here please). , isn't one of them.

不,你不能。宏有一组可以用来命名它们的特定字符(请参阅这里的详细信息)。,不是其中之一。

#3


4  

Go shopping for the latest C++14 compliant compiler. That allows you to use ' as a thousands separator:

购买最新的c++ 14兼容编译器。这样你就可以使用“作为千位分隔符:

#define MAX 10'000'000

#定义MAX 000‘000’

although using a macro in such a brand spanking new C++ compiler is an anachronism.

尽管在这种全新的c++编译器中使用宏是不合时宜的。

Writing 10,000,000 would not end well. If used in an expression then , will stand in for the comma operator.

写1000万不会有好结果。如果在表达式中使用,则表示逗号运算符。

So int a = (10,000,000) would be zero. It could be worse than that: a leading zero denotes an octal literal, so int a = (10,000,010) would actually be 8.

所以int a =(10,000,000) = 0。更糟糕的是:前导0表示八进制,所以int a =(10,000,010)实际上是8。

#4


2  

Sort of, although it's a bit tedious and inelegant:

虽然有点乏味不雅

#define constant(a) (a)
#define constant2(a,b) (a##b)
#define constant3(a,b,c) (a##b##c)

constant(10000)
constant2(10,000)
constant3(10,000,000)

#5


1  

You can always use a custom function that will parse a string literal:

您总是可以使用一个自定义函数来解析字符串文字:

int value = Number( "100,000,000" );

The downsite is the some small overhead for parsing, and the benefits are error checking, and the ability to use any format you want.

下站点是解析的一些小开销,其好处是错误检查,以及使用任何您想要的格式的能力。

The parsing itself can be minimized by reusing const varibles in outer most scopes.

解析本身可以通过在大多数外部作用域中重用const变量来最小化。

#6


1  

One trick to enhance code clarity is to define macro as:

提高代码清晰度的一个技巧是将宏定义为:

#define MAX    (10 * 1000 * 1000)

The rationale is that modern compilers are smart enough to simplify the expression into single integer constant 10000000. This is known as constant propagation (or constant folding).

基本原理是,现代编译器足够聪明,可以将表达式简化为单个整数常量10000000。这被称为常数传播(或常数折叠)。