В чем разница между 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).)

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