Определить # определенную длину строки во время компиляции - PullRequest
18 голосов
/ 23 октября 2010

У меня есть C-программа (модуль Apache, т. Е. Программа часто запускается), которая собирается write() 0-концевая строка через сокет, поэтому мне нужно знать ее длину.

Строка # определена как:

#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 уже во время компиляции?

Ответы [ 4 ]

34 голосов
/ 23 октября 2010

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

6 голосов
/ 15 января 2014

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

2 голосов
/ 23 октября 2010

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! */
1 голос
/ 11 декабря 2017

У меня похожая проблема при использовании устаревшего компилятора (VisualDSP) на встроенной платформе, которая еще не поддерживает C ++ 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 символов.В моем случае этого достаточно, но в случае OP может потребоваться расширение макроса (много).Поскольку он очень повторяющийся, вы можете легко написать сценарий для создания макроса, который принимает 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"))
...