Преамбула: я не могу в это поверить! Я был озадачен таким выражением, когда меня учили основам Си (без каламбура). Вот почему я углубляюсь в подробности в разделе «Анализ кода».
Разбор кода
Первая проблема - парсинг кода
Добро пожаловать в сумеречную зону
str = (char *) malloc (sizeof(char) * (num+1));
При работе с C / C ++ синтаксический анализ этого вида выражения является обязательным, поэтому мы разбим его на его компоненты. Первое, что мы видим здесь, это что-то вроде:
variable = (expression) function (expression) ;
Когда я впервые увидел это, я просто сказал: «Эй, я не могу поверить, что есть язык программирования, где вы можете вызывать функцию, помещая ее параметры слева и справа от вызова функции!».
Разбор этой строки кода?
По правде говоря, эту строку следует читать так:
variable = function_a (function_b (expression)) ;
где:
expression is sizeof(char) * (num+1)
function_b is malloc
function_a is a cast operator
Оператор приведения C немного меньше естественного
Как уже объяснялось в другом месте, оператор приведения в стиле C больше похож на
(function_a) expression
чем естественнее
function_a(expression)
Что объясняет странность всей строки кода.
Есть ли в C ++ что-то более понятное?
Обратите внимание, что в C ++ вы можете использовать обе нотации, но вместо них вы должны использовать static_cast, const_cast, reinterpret_cast или dynamic_cast вместо вышеуказанных нотаций. При использовании C ++ приведенная выше строка кода будет выглядеть так:
str = static_cast<char *> ( malloc (sizeof(char) * (num+1)) ) ;
Мой размер больше вашего
sizeof является оператором. Вы можете думать это как функция, работающая с типами.
Вы передаете тип в качестве параметра, и он даст вам свой размер в байтах.
Итак, если вы напишите:
size_t i = sizeof(char) ;
size_t j = sizeof(int) ;
Вероятно, у вас (в 32-битном Linux) будет значение 1 для i и 4 для j.
Его использование в malloc похоже на выражение «я хочу достаточно места, чтобы разместить 25 автомобилей длиной 4 метра» вместо «я хочу хотя бы 100 метров».
Что-то есть в Маллоке
Параметр Malloc - это size_t, то есть целое число без знака. Вы даете ему размер в байтах, и в случае успеха он возвращает вам адрес выделенной памяти, достаточно большой для использования в качестве массива. Например:
int * p = (int *) malloc (25 * sizeof(int)) ;
Тогда p указывает на память, где вы можете поместить 25 целых чисел рядом, как будто внутри массива, индексы которого идут от нуля до размера minux один. Например:
p[0] = 42 ; // Ok, because it's the 1st item of the array
p[24] = 42 ; // Ok, because it's the 25th item of the array
p[25] = 42 ; // CORRUPTION ERROR, because you are trying to
// use the 26th item of a 25 items array !
Примечание: у вас тоже есть арифметика с указателями, но это выходит за рамки вопроса.
число + 1?
Строки в стиле C несколько отличаются от строк других языков.
Каждый символ строки может иметь любое значение, НО НЕ НОЛЬ.
Поскольку ноль (также отмеченный \ 0) отмечает конец строки c.
Другими словами: вы никогда не узнаете размер c-строки, но, выполнив поиск символа \ 0, вы сможете узнать, где он заканчивается (кстати, это одна из причин переполнения буфера и повреждения стека).
Например, строка «Hello» имеет 5 символов:
"Hello" seems to be an array containing 'H', 'e', 'l', 'l' and 'o'.
Но по правде говоря, он имеет 6 символов, последний из которых - символ ZERO, который отмечается с помощью escape-символа \ 0. Таким образом:
"Hello" is an array containing 'H', 'e', 'l', 'l', 'o' and 0.
Это объясняет, что когда вы хотите выделить достаточно места для строки из «num» символов, вы выделяете вместо «num + 1» символы.