В чем разница между alloca(n) и char x[n]?
В чем разница между
void *bytes = alloca(size);
а также
char bytes[size]; //Or to be more precise, char x[size]; void *bytes = x;
... где размер - это переменная, значение которой неизвестно во время компиляции.
6 ответов
alloca()
не восстанавливает память до тех пор, пока текущая функция не завершится, в то время как массив переменной длины восстанавливает память, когда текущий блок заканчивается.
Перефразируй:
void foo()
{
size_t size = 42;
if (size) {
void *bytes1 = alloca(size);
char bytes2[size];
} // bytes2 is deallocated here
}; //bytes1 is deallocated here
alloca()
может поддерживаться (в моде) на любом компиляторе C89, в то время как массив переменной длины требует компилятора C99.
Из документации GNU:
Пространство, выделенное с помощью alloca, существует, пока не вернется содержащая функция Пространство для массива переменной длины освобождается, как только заканчивается область действия имени массива. (Если вы используете массивы переменной длины и alloca в одной и той же функции, освобождение массива переменной длины также приведет к освобождению всего, что было недавно выделено с помощью alloca.)
Дополнительно, alloca
не является стандартной функцией C, поэтому поддержка не гарантируется для всех компиляторов. Массивы переменной длины являются частью стандарта C99, поэтому любой компилятор, поддерживающий C99, должен реализовывать его.
Помимо того, что упомянул Билли, alloca
не является стандартным (это даже не в C99).
Самая большая разница в том, что alloca не вызывает конструкторы или деструкторы, когда вы используете память в качестве переменных класса.
Другие различия менее заметны, но могут проявляться в некоторых странных ошибках во время выполнения в некоторых ситуациях.
Во втором классе size
должна быть константа, известная для компиляции времени.
Помимо уже обсуждаемых моментов, когда именно пространство освобождается, и поддерживается ли конструкция вообще, есть также следующее:
- в
alloca
дело,bytes
имеет тип указателя. - в
[]
дело,bytes
имеет тип массива.
Самая заметная разница в том, что sizeof(bytes)
является; для указателя это размер указателя (sizeof(void *)
) тогда как для массива это размер выделенного пространства (sizeof(char) * size
который = size
для этого случая, так как sizeof(char)
= 1)
(Кроме того, в вашем примере типы элементов различаются; чтобы быть одинаковыми, первый должен быть изменен на char *bytes = alloca(size)
.)