У меня есть два вопроса:
Я прав, что в 4-битных системах указатель составляет 4 байта?
«Передача по ссылке» и «Передача по указателю» — это одно и то же, просто разные формулировки?
Я прав, что в 4-битной системе размер указателя равен 4
Если ваша система имеет 1-битные байты, то это точно. (Но C не поддерживает платформы, где байты короче 8 бит).
«Передача по ссылке» и «Передача по указателю» — это одно и то же, но разные формулировки?
Нет. Pass-by-pointer — это подход на языке C для эмуляции передачи по ссылке. Концепция отличается.
Размер указателя не обязательно соотносится с собственным размером слова ЦП; Например, оригинальный Macintosh работал на 32-битном процессоре (Motorola 68000), который имел только 24 адресных строки, поэтому указатели были ограничены 24 битами. Значение указателя было сохранено в 32-битном слове, но верхние 8 бит не использовались. Некоторые предприимчивые программисты использовали эти старшие 8 бит для хранения других данных с указателем. Это вызвало некоторую изжогу, когда вышел 68020 с 32 адресными строками. Потребовалось время, чтобы переписать этот код так, чтобы он был «32-битным чистым».
Также обратите внимание, что указатели на разные типы не обязательно должны быть одинакового размера.
На практике в любой современной настольной системе (читай: x86) все типы указателей будут иметь ширину 32 или 64 бита. Но не надейтесь, что это верно для всех архитектур.
Что касается передачи «передача по ссылке» и «передача по указателю», то нет, это не просто разные формулировки одного и того же понятия.
В системе передачи по ссылке формальный параметр в определении функции и фактический параметр в вызове функции назначают ту же память (или, по крайней мере, изменения одного отражаются в другом). Глядя на какой-то старый код Fortran:
C234567890
PROGRAM CALLSW
INTEGER M, N
M = 1
N = 2
WRITE(*,*) M, N
CALL ISWAP(M, N)
WRITE(*,*) M, N
STOP
END
C234567890
SUBROUTINE ISWAP(A, B)
INTEGER A, B
INTEGER TMP
TMP = A
A = B
B = TMP
RETURN
END
Формальный параметр A
в ISWAP
обозначает тот же объект в памяти, что и M
в основной программе, так что писать A
изменяет значение в M
, Вы можете думать о A
как указатель на M
(или это A
а также M
оба указателя на один и тот же объект), но язык скрывает указатель от программиста.
С проходит все мимо значение; формальный параметр и фактический параметр всегда обозначают разные объекты в памяти, поэтому запись в один не влияет на другой. Когда мы хотим изменить объект в подпрограмме, мы должны явно передать его адрес, используя &
оператор, а затем разыменовывать его в подпрограмме с *
оператор:
void iswap(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
int main(void)
{
int m, n;
m = 1;
n = 2;
printf("m = %d, n = %d\n", m, n);
iswap(&x, &y);
printf("m = %d, n = %d\n", m, n);
return 0;
}
Вместо прохождения m
а также n
в iswap
мы передаем результаты выражения &m
а также &n
, которые являются указателями на два объекта. Точно так же в iswap
функция, мы не пишем a
или же b
мы пишем результаты выражения *a
а также *b
, a
а также m
ссылаются на два совершенно разных объекта в памяти, а также b
а также n
, Запись в a
не повлияет m
совсем.
Что касается передачи параметров в C, Википедия на C состояния:
Параметры функции всегда передаются по значению. Передача по ссылке моделируется в C путем явной передачи значений указателя.