Ale*_*ber 21 c macros c-strings strlen c-preprocessor
我有一个C程序(一个Apache模块,即程序经常运行),它将write()通过套接字转到0端接的字符串,所以我需要知道它的长度.
字符串#defined为:
#define POLICY "<?xml version=\"1.0\"?>\n" \
"<!DOCTYPE cross-domain-policy SYSTEM\n" \
"\"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">\n" \
"<cross-domain-policy>\n" \
"<allow-access-from domain=\"*\" to-ports=\"8080\"/>\n" \
"</cross-domain-policy>\0"
Run Code Online (Sandbox Code Playgroud)
请问一种方法,比strlen(POLICY)+1在运行时使用更好(从而一次又一次地计算长度)?
一个预处理器指令,它允许POLICY_LENGTH在编译时设置?
Oli*_*rth 37
使用sizeof().例如,sizeof("blah")将5在编译时评估(5,而不是4,因为字符串文字总是包含一个隐式的空终止字符).
小智 6
I have a similar problem when using an outdated compiler (VisualDSP) on an embedded platform which does not yet support C++11 (and so I can't use constexpr).
I don't need to evaluate the string length in the precompiler, but I do need to optimize it into a single assignment.
Just in case someone needs this in the future, here's my extremely hacky solution which should work on even crappy compilers as long as they do proper optimization:
#define STRLENS(a,i) !a[i] ? i : // repetitive stuff
#define STRLENPADDED(a) (STRLENS(a,0) STRLENS(a,1) STRLENS(a,2) STRLENS(a,3) STRLENS(a,4) STRLENS(a,5) STRLENS(a,6) STRLENS(a,7) STRLENS(a,8) STRLENS(a,9) -1)
#define STRLEN(a) STRLENPADDED((a "\0\0\0\0\0\0\0\0\0")) // padding required to prevent 'index out of range' issues.
Run Code Online (Sandbox Code Playgroud)
This STRLEN macro will give you the length of the string literal that you provide it, as long as it's less than 10 characters long. In my case this is enough, but in the OPs case the macro may need to be extended (a lot). Since it is highly repetitive you could easily write a script to create a macro that accepts 1000 characters.
PS: This is just a simple offshoot of the problem I was really trying to fix, which is a statically-computed HASH value for a string so I don't need to use any strings in my embedded system. In case anyone is interested (it would have saved me a day of searching and solving), this will do a FNV hash on a small string literal that can be optimized away into a single assignment:
#ifdef _MSC_BUILD
#define HASH_FNV_OFFSET_BASIS 0x811c9dc5ULL
#define HASH_TYPE int
#else // properly define for your own compiler to get rid of overflow warnings
#define HASH_FNV_OFFSET_BASIS 0x811c9dc5UL
#define HASH_TYPE int
#endif
#define HASH_FNV_PRIME 16777619
#define HASH0(a) (a[0] ? ((HASH_TYPE)(HASH_FNV_OFFSET_BASIS * HASH_FNV_PRIME)^(HASH_TYPE)a[0]) : HASH_FNV_OFFSET_BASIS)
#define HASH2(a,i,b) ((b * (a[i] ? HASH_FNV_PRIME : 1))^(HASH_TYPE)(a[i] ? a[i] : 0))
#define HASHPADDED(a) HASH2(a,9,HASH2(a,8,HASH2(a,7,HASH2(a,6,HASH2(a,5,HASH2(a,4,HASH2(a,3,HASH2(a,2,HASH2(a,1,HASH0(a))))))))))
#define HASH(a) HASHPADDED((a "\0\0\0\0\0\0\0\0\0"))
Run Code Online (Sandbox Code Playgroud)