首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >要计算(字符)参数的宏

要计算(字符)参数的宏
EN

Stack Overflow用户
提问于 2011-08-08 12:45:53
回答 3查看 1.1K关注 0票数 4

我有一个宏来将一个字符串转换为一个字符列表:

代码语言:javascript
复制
#define TO_STRING(x) #x
#define CHAR_LIST_7(x)   TO_STRING(x)[0] \
                       , TO_STRING(x)[1] \
                       , TO_STRING(x)[2] \
                       , TO_STRING(x)[3] \
                       , TO_STRING(x)[4] \
                       , TO_STRING(x)[5] \
                       , TO_STRING(x)[6]

例如,用法:“CHAR_LIST_7(鸡)”表示"'c','h','i','c','k','e','n'“,所以它可以用在模板中(例如:http://hpaste.org/47313/exand )

但是,我想将其推广到任意数量的字符(而不需要手动计算字符数)?所以我可以简单地说:CHAR_LIST(任意文本)。有什么想法或解决方案吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-08-08 12:52:26

你不能在预处理过程中拆分令牌,只能组合它们(使用##)。

将标识符转换为字符串文字也没有帮助,因为您不能在预处理过程中将字符串文字拆分开,也不能对字符串文字执行操作(例如计算长度)。

在预处理期间,编译器知道标记是字符串文字以及它是哪种文字,但它还不知道它的完整类型和长度,至少不知道宏可以访问的方式。

票数 3
EN

Stack Overflow用户

发布于 2011-08-08 14:16:49

你要求拆分的方式在一般形式下是不可能的。最好的方法是将参数原样提供给template

代码语言:javascript
复制
Literal<'c','h','i','c','k','e','n'>::print();

我知道这需要更多的打字。为了克服这个问题,你可以编写一个简单的程序,它接受一个像chicken这样的字符串作为参数,并将它输出到'c''h''i',...etc中。类似于:

代码语言:javascript
复制
int main(int argc, char **argv)
{
  if(argc != 2)
    return 0;
  const char *s = argv[1];
  int length = strlen(s)-1;
  for(int i = 0; i < length; i++)
    cout<<s[i]<<",";
  cout<<s[length]<<endl;
}

但是,由于template参数中包含拆分字符,因此没有解决冗长问题的解决方案。

票数 1
EN

Stack Overflow用户

发布于 2011-08-08 14:50:32

不,正如James已经说过的,没有办法在预处理器中拆分标记,或者让它知道字符串的长度。

但我认为,对于您的用例,这在任何情况下都是没有必要的。通过使用#x将参数字符串化得到的字符串是一个固定大小的字符串,例如,chicken通向"chicken",它只有char[8]类型。这样字符串的长度是一个编译时间常数,您可以使用sizeof简单地检测它

代码语言:javascript
复制
#define TOKLEN(TOK) (sizeof(#TOK)-1)

在C中使用这样的东西看起来“很简单”

代码语言:javascript
复制
#define SCARY(TOK) for (size_t i = 0; i < TOKLEN(TOK); ++i) printf("%c:", #TOK[i])

因为TOKLEN(TOK)是一个编译时间常量,所以如果合适的话,编译器可以展开它。

在您的C++用例中使用它

代码语言:javascript
复制
template < size_t n >
class constLenString {
  size_t const len = n;
  char const* str;
  constLenString(char* s) : str(s) { }
};

#define defConstLenString(TOK, NAME) constLenString< TOKLEN(TOK) > NAME(#TOK)

(未经测试,我的C++已生锈)

现在有了

代码语言:javascript
复制
defConstLenString(chicken, chick);

chick.n是一个常量,它可以是for循环或其他任何东西的界限,编译器应该能够完美地优化一切。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6977847

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档