Подтвердить что ты не робот

Как sizeof (массив) работает во время выполнения?

Я прочитал, что оператор sizeof в C интерпретируется во время компиляции, и поскольку во время компиляции компилятор знает размер массива и его тип, sizeof abled, чтобы вычислить количество байтов, занятых массивом. Но как работает sizeof для следующий код:

 #include<stdio.h>
 #include<string.h>
 int main()
 {
    int n;
    scanf("%d",&n);
    int a[n];
    int s=sizeof(a);
    printf("%d",s);
    return 0;
 }

Здесь размер массива неизвестен во время компиляции, тогда как он работает правильно?

4b9b3361

Ответ 1

sizeof всегда вычисляется во время компиляции в C89. Поскольку C99 и массивы переменной длины вычисляются во время выполнения, когда массив переменной длины является частью выражения в операнде sizeof.

То же самое для оценки операнда sizeof: он не оценивается на C89, а на C99, если операнд имеет тип массива переменной длины, он оценивается. Например:

int n = 5;
sizeof (int [n++]); 

// n is now 6

Ответ 2

Поскольку вы применяете sizeof к массиву переменной длины, размер которого не полностью известен во время компиляции, компилятор должен генерировать код, чтобы сделать его частью во время выполнения.

gcc 4.6.3 оптимизаторы высокого уровня преобразуют код, который вы указали в

scanf ("%d", &n);
t12 = (long unsigned int) n;
t13 = t12 * 4;
__builtin_alloca (t13);
t16 = (unsigned int) t12;
t17 = t16 * 4;
s18 = (int) t17;
printf ("%d", s18);

Объясняет ли это, что происходит под капотом? (Не отвлекайтесь на глупое количество временных переменных - что артефакт программы, находящийся в статическом одиночном назначении, формируется в точке, где я спросил для дампа промежуточного кода.)

Ответ 3

Из стандарта C99:

6.5.3.4

Оператор sizeof дает размер (в байтах) своего операнда, который может быть выражение или имя в скобках типа. Размер определяется по типу операнд. Результат - целое число. Если тип операнда представляет собой массив переменной длины тип, операнд оценивается; в противном случае операнд не оценивается, и результат целочисленная константа.

Ответ 4

В этом случае sizeof() оценивается во время выполнения. Компилятор, поскольку он знает, что размер a основан на значении n во время объявления массива, генерирует код для использования соответствующего значения n для возврата разумного значения для sizeof().

В C99 не все виды использования sizeof() могут быть полностью оценены во время компиляции и сокращены до постоянной времени выполнения.

Ответ 5

Я прочитал, что оператор sizeof в C интерпретируется в время компиляции

sizeof определяется во время компиляции во всех случаях, кроме VLA. Для VLA sizeof оценивается во время выполнения.

Ответ 6

Независимо от того, вычисляется ли sizeof во время компиляции или во время выполнения (или более формально говоря, является ли его результат целочисленным константным выражением), результат sizeof основан исключительно на типе его аргумента, а не любые скрытые данные, сопровождающие массив переменной длины. Конечно, когда sizeof применяется к изменяемому варианту типа, созданная программа должна отслеживать этот размер где-то. Но он мог бы просто пересчитать его, если выражение было достаточно простым, а переменные, изначально выведенные из длины, не могли быть изменены. Или он может хранить размер типа где-то (по существу, в скрытой локальной переменной), но это не будет связано с объектом VLA любым наблюдаемым способом (например, если вы передадите указатель на первый элемент VLA к другой функции, этот указатель не может использоваться для восстановления длины VLA).