Определение длины строкового литерала

Учитывая массив указателей на строковые литералы:

char *textMessages[] = {
    "Small text message",
    "Slightly larger text message",
    "A really large text message that "
    "is spread over multiple lines"
}

Как определить длину конкретного строкового литерала - скажем, третьего? Я попытался использовать команду sizeof следующим образом:

int size = sizeof(textMessages[2]);

Но результатом является количество указателей в массиве, а не длина строкового литерала.

Ответ 1

Если вы хотите, чтобы число, вычисленное во время компиляции (в отличие от во время выполнения с strlen), вполне нормально использовать выражение типа

sizeof "A really large text message that "
       "is spread over multiple lines";

Возможно, вы захотите использовать макрос, чтобы избежать повторения длинного литерала:

#define LONGLITERAL "A really large text message that " \
                    "is spread over multiple lines"

Обратите внимание, что значение, возвращаемое sizeof, включает в себя завершающий NUL, так что это больше, чем strlen.

Ответ 2

Мое предложение состояло в том, чтобы использовать strlen и включить оптимизацию компилятора.

Например, с gcc 4.7 на x86:

#include <string.h>
static const char *textMessages[3] = {
    "Small text message",
    "Slightly larger text message",
    "A really large text message that "
    "is spread over multiple lines"
};

size_t longmessagelen(void)
{
  return strlen(textMessages[2]);
}

После запуска make CFLAGS="-ggdb -O3" example.o:

$ gdb example.o
(gdb) disassemble longmessagelen
   0x00000000 <+0>: mov    $0x3e,%eax
   0x00000005 <+5>: ret

т.е. компилятор заменил вызов на strlen постоянным значением 0x3e = 62.

Не тратьте время на выполнение оптимизаций, которые компилятор может сделать для вас!

Ответ 3

strlen может быть?

size_t size = strlen(textMessages[2]);

Ответ 4

Вы должны использовать метод библиотеки strlen() для получения длины строки. sizeof даст вам размер textMessages[2], указатель, который будет зависящим от машины (4 байта или 8 байтов).

Ответ 5

strlen дает длину строки, тогда как sizeof возвращает размер Тип данных в байтах, которые вы ввели как параметр.

strlen

sizeof

Ответ 6

Вы можете использовать тот факт, что значения в массиве последовательны:

const char *messages[] = {
    "footer",
    "barter",
    "banger"
};

size_t sizeOfMessage1 = (messages[1] - messages[0]) / sizeof(char); // 7   (6 chars + '\0')

Размер определяется с помощью границ элементов. Пространство между началом первого и началом второго элемента является размером первого.

Это включает завершение \0. Решение, конечно, работает только с постоянными строками. Если бы строки были указателями, вы бы указали размер указателя вместо длины строки.

Не гарантируется работа. Если поля выровнены, это может привести к неправильным размерам, и могут возникнуть другие оговорки, введенные компилятором, например, слияние идентичных строк. Также вам понадобится как минимум два элемента в вашем массиве.

Ответ 7

Я расскажу вам кое-что, согласно моим массивам Knowledge указатели - это то же самое кроме, когда вы используете sizeof.

Когда вы используете sizeof в указателе, он всегда будет всегда 4 BYTE, независимо от того, на что указывает указатель, но если он используется в массиве, он вернет . большой в байтах?.

В вашем примере здесь *textMessage[] является массивом указателя, поэтому, когда вы используете sizeof(textMessage[2]), он вернет 4 BYTE, потому что textMessage[2] является указателем.

Я надеюсь, что это будет полезно для вас.