C передает массив функции не по ее содержимому, а по адресу.
Следовательно, аргумент функции на самом деле является простым int *
и значением, которое вам необходимо отправить.это a.Address
.
Давайте представим ваш гипотетический язык, хотя.Если семантика вашего языка требует, чтобы массив отправлялся в функцию по ее содержимому, вам нужно будет использовать stack , поскольку параметры функции находятся в стеке.
Обратите внимание, что это приносит еще одно осложнение:
Давайте рассмотрим эту функцию:
int f(int arg1, struct some_struct arg2, float arg3);
и давайте вызовем некоторый указатель внутри этой функции как указатель на фрейм стека этой функции.Давайте назовем это bp
(базовый указатель).
Итак, в функции вы знаете, что arg1
находится по адресу bp+8
(например), arg2 находится по адресу bp+12
и arg3
находится по адресу bp+36
(при условии sizeof(struct some_struct)
равно 20)
Теперь, если вы отправляете массивы по их содержимому, как насчет этой функции?
int f(int arg1, int arg2[], float arg3);
arg1
и arg2
находятся в том же месте, но как насчет arg3
?Как вы узнали бы местонахождение arg3
?Для этого вам нужно знать размер arg2
.
Однако есть решение для этого.Вы можете сохранить размер массива в его первых 4 байтах (или 8 байтах, если вы считаете, что массив может быть больше 4 ГБ).Затем вы можете безопасно передавать массивы по их содержимому (включая их размер).В таком случае адрес a[i]
будет a.Address+4(or 8)+i*sizeof(*a)
.
. Необходимо учитывать несколько компромиссов:
- Дополнительная память для сохранения размерамассив.Раньше это было проблемой во время рождения C, но теперь, возможно, это больше не проблема.
- Гораздо медленнее время вызовов функций, потому что нужно копировать массивы.
- Более надежный кодпотому что связанная проверка может быть сделана во время выполнения.Мне лично это не нравится, хотя вы выполняете медленнее, и ваша программа все равно не должна выходить за границы массива!Это может быть очень полезной опцией для режима отладки.
- Лучшая
sizeof
операция для массивов, которая фактически дает размер массива.Это может быть полезно для функций, которые просто получают массив без его размера.Например, strlen
будет O (1). - Указатели на середину массива будут бесполезны.Подумайте, сортировка слиянием.
- и т. Д.