Преобразование int в строку все еще работает, даже когда вызывает переполнение буфера - PullRequest
0 голосов
/ 16 апреля 2020

Я пытаюсь преобразовать int в строку C, используя этот код:

static char* copyString(const char* str)  
{
    char* new_String = malloc(strlen(str) + 1);
    return strcpy(new_String, str);
}
static char* mallocIntToString(const int num)
{
    char s[10]; // *************
    sprintf(s, "%d", num);
    char* copy = copyString(s);

    return copy;
}

Я бродил, какое самое большое число я должен вставить в строку char s[10];.

Я использовал 10, потому что это максимальные цифры для целого числа. Тем не менее, этот код также работает для меня, когда я использую char s[9];, пытаясь преобразовать число 2147483647 в строку, как это возможно?

1 Ответ

1 голос
/ 16 апреля 2020

Я бродил, какое наибольшее число я должен вставить в строку char s[10];.

Вы должны вставить максимальную длину между INT_MAX и INT_MIN, определенную в <limits.h>. INT_MIN должно быть -2147483648, поэтому вам нужно 11 + 1 = 12 символов (дополнительный - для ограничителя строки \0).

Правильная реализация будет:

static char* mallocIntToString(const int num)
{
    char *s;

    s = malloc(12);
    if (s == NULL)
        return NULL;

    sprintf(s, "%d", num);    
    // Should probably also check for error here.

    return s;
}

Однако этот код также работает для меня, когда я использую char s[9];, пытаясь преобразовать число 2147483647 в строку, как это возможно?

Вы вызываете неопределенное поведение, так как запись после конца массива является неопределенным поведением. При этом все может случиться. Программа не гарантированно работает правильно, но из чистого совпадения , она все равно может работать . Что происходит в вашем коде, так это то, что поскольку переменная определена в стеке и стек доступен для записи, запись на один или два байта больше не сильно изменится, потому что программа все еще записывает в допустимую память. С учетом вышесказанного, это все еще неопределенное поведение, и его следует избегать любой ценой!

Чтобы быть на 100% ясным, вы будете вызывать неопределенное поведение даже с char s[10]; или char s[11];, потому что в случае INT_MIN терминатор будет записан вне границ массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...