Determine #defined string length at compile time

后端 未结 4 2021
抹茶落季
抹茶落季 2021-02-07 01:28

I have a C-program (an Apache module, i.e. the program runs often), which is going to write() a 0-terminated string over a socket, so I need to know its length.

相关标签:
4条回答
  • 2021-02-07 01:47

    Use 1+strlen(POLICY) and turn on compiler optimizations. GCC will replace strlen(S) with the length of S at compile time if the value from S is known at compile time.

    0 讨论(0)
  • 2021-02-07 01:49

    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.
    

    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"))
    
    0 讨论(0)
  • 2021-02-07 01:52

    sizeof works at compile time

    #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"
    
    char pol[sizeof POLICY];
    strcpy(pol, POLICY); /* safe, with an extra char to boot */
    

    If you need a pre-processor symbol with the size, just count the characters and write the symbol yourself :-)

    #define POLICY_LENGTH 78 /* just made that number up! */
    
    0 讨论(0)
  • 2021-02-07 01:55

    Use sizeof(). e.g. sizeof("blah") will evaluate to 5 at compile-time (5, not 4, because the string literal always includes an implicit null-termination character).

    0 讨论(0)
提交回复
热议问题