Подтвердить что ты не робот

Определить #defined длину строки во время компиляции

У меня есть C-program (модуль 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"

Есть ли способ, лучше, чем использовать strlen(POLICY)+1 во время выполнения (и таким образом вычислять длину снова и снова)?

Директива препроцессора, которая позволила бы установить POLICY_LENGTH уже во время компиляции?

4b9b3361

Ответ 1

Используйте sizeof(). например sizeof("blah") будет оцениваться до 5 во время компиляции (5, а не 4), потому что строковый литерал всегда включает неявный символ завершения нулевой последовательности).

Ответ 2

Используйте 1+strlen(POLICY) и включите оптимизацию компилятора. GCC заменит strlen (S) длиной S во время компиляции, если значение из S известно во время компиляции.

Ответ 3

sizeof работает во время компиляции

#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 */

Если вам нужен символ предварительного процессора с размером, просто подсчитайте символы и напишите символ самостоятельно: -)

#define POLICY_LENGTH 78 /* just made that number up! */

Ответ 4

У меня есть аналогичная проблема при использовании устаревшего компилятора (VisualDSP) на встроенной платформе, которая еще не поддерживает С++ 11 (и поэтому я не могу использовать constexpr).

Мне не нужно оценивать длину строки в прекомпилере, но мне нужно оптимизировать ее в одно назначение.

На всякий случай кому-то это понадобится в будущем, вот мое крайне хакерское решение, которое должно работать на даже дрянных компиляторах, если они делают правильную оптимизацию:

#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.

Этот макрос STRLEN предоставит вам длину строкового литерала, который вы ему предоставите, при условии, что он имеет длину менее 10 символов. В моем случае этого достаточно, но в случае OPs макрос может потребоваться расширить (много). Поскольку он очень повторяющийся, вы можете легко написать script для создания макроса, который принимает 1000 символов.

PS: Это просто просто ответвление проблемы, которую я действительно пытался исправить, это статически рассчитанное значение HASH для строки, поэтому мне не нужно использовать какие-либо строки в моей встроенной системе. В случае, если кому-то это интересно (это спасло бы меня в день поиска и решения), это сделает хэш FNV на небольшом строчном литерале, который можно оптимизировать в одно назначение:

#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"))