Лучший способ получить длину const char * в C++

Я знаю два способа получить длину константного символа *

const char * str = "Hello World !";
int Size = 0;
while (str[Size] != '\0') Size++;

а другой способ очень прост

const char * str = "Hello World !";
size_t Size = strlen(str);

но я не хочу использовать функции str lib, такие как strlen и я думаю, что эта функция также использует мой первый способ поведения. потому что в мире ПК, когда мы хотим посчитать что-то, нам нужно сосчитать каждый блок, и нет никакого волшебства, чтобы получить длину одним движением, поэтому я думаю, что первый способ - лучший вариант, чтобы получить длину const char *, иначе я думаю, что первый путь может быть слишком тяжелым для тяжелой струны. Я в замешательстве. какой путь лучше, а другой нет?

3 ответа

Решение

Давайте проверим список сборки этих двух методов.

#include <cstddef>
#include <cstring>

int string_size_1()
{
    const char * str = "Hello World !";
    int Size = 0;
    while (str[Size] != '\0') Size++;
    return Size;
}

int string_size_2()
{
    const char * str = "Hello World !";
    size_t Size = strlen(str);
    return Size;
}

Использование Clang 4.0.0 с флагами -std=c++14 -O2

string_size_1():                     # @string_size_1()
        mov     eax, 13
        ret

string_size_2():                     # @string_size_2()
        mov     eax, 13
        ret

Ссылка: https://godbolt.org/g/5S6VSZ

Оба метода приводят к одному и тому же листу сборки. Кроме того, компилятор оптимизирует все и просто возвращает константу, потому что строковый литерал известен во время компиляции. Так что с точки зрения производительности они одинаково хороши.

Но с точки зрения читабельности, strlen(str) определенно лучше Вызов функции устанавливает намерение через имя функции. Цикл не может этого сделать.


Кроме того, std::string а также std::string_view во многих случаях предпочтительнее, чем C-строка. Считай их.

В этом случае ответ известен во время компиляции:

template <std::size_t S>
constexpr std::size_t string_length
(
    char const (&)[S]
)
{
    return S - 1;
}

использование:

std::cout << string_length("example") << std::endl;

Для случаев, когда строка не является постоянной времени компиляции, используйте strlen, если доступен только указатель на строку, std:: distance, если доступны оба указателя на начало и конец, или.size(), если вы имеете дело со std:: строка

На 3 года позже, но лучше поздно, чтобы никогда.

Короткий ответ


Длинный ответ

Итак, используя sizeof(array) возвращается the size of the type of the array * the amount of elements. Зная это, мы могли бы добиться этого:

      #define length(array) ((sizeof(array)) / (sizeof(array[0])))

и вы бы использовали его так:

      type yourArray[] = {your, values};
length(yourArray);    // returns length of yourArray

Например:

      #include <stdlib.h>
#include <stdio.h>

#define length(array) ((sizeof(array)) / (sizeof(array[0])))


int main()
{
    const char *myStrings[] = {"Foo", "Bar", "Hello, World!"};    // 3 elements
    int myNums[] = {0, 1, 5, 7, 11037};    // 5 elements
    char myChars[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};    // 7 elements

    printf("Length of myStrings array: %lu\n", length(myStrings));
    printf("Length of myNums array: %lu\n", length(myNums));
    printf("Length of myChars array: %lu\n", length(myChars));

    return 0;

    /* Output:
           Length of myStrings array: 3
           Length of myNums array: 5
           Length of myChars array: 7 */
}

Я тестировал его, и он также работает с неинициализированными массивами, вероятно, потому, что они содержат мусор (от неинициализированного) того же типа. Целочисленные неинициализированные массивы содержат случайные целые числа, а неинициализированные массивы const char * содержат (null), который рассматривается как const char*.

Теперь это работает только с массивами в стеке. Указатели, указывающие на пространство, зарезервированное в куче, используемом в качестве массива, могут дать неожиданные результаты. Например:

      int *myNums = (int *)malloc(3 * sizeof(int));    // Space for 3 integers
printf("Length of myNums: %lu\n");  // Outputs 2 instead of 3

Так что имейте в виду. Кто вообще использует массивы в куче, да ладно.

Примечание. Это относится к этому вопросу, поскольку работает с const char * по запросу. Также работает с другими типами.

Другие вопросы по тегам