Выяснение адресов в C [закрыто]
Я пытаюсь узнать, как вычислить адреса в C. Для кода ниже, предполагая, что он скомпилирован на 32-битной маленькой машине endian.
struct {
int n;
char c;
} A[10][10];
Скажем, адрес A[0] [0] равен 1000 (десятичный), каким будет адрес A[3][7]? Любая помощь ценится!
5 ответов:
C являетсяупорядоченным по строкам , что означает, что сначала вычисляется самый левый индекс. Таким образом:
&A[3] == 1000 + (3 * 10 * sizeof(your_struct))
Чтобы найти столбец, мы просто добавляем оставшийся индекс:
&A[3][7] == 1000 + (3 * 10 * sizeof(your_struct)) + (7 * sizeof(your_struct))
Обратите внимание, что это не имеет ничего общего с архитектурой big-endian vs little-endian. Это просто расположение байтов в слове, в то время как вы хотите расположение структур в массиве.Кроме того,
Наконец, 32-битная природа вашей машины означает, что размер регистра адреса памяти равен 32 битам. (Или, говоря по-другому,sizeof(your_struct)
не гарантированно будетsizeof(n) + sizeof(c)
, потому что компилятор может дополнить ваш структура.sizeof(void*)==32
). Это показатель того, сколько памяти ваш процессор может на самом деле назначить адрес. Это отдельная проблема от размера типов данных в C.
Это зависит не от стандарта языка Си, а от компилятора, версии компилятора и ОС, которую вы используете/targeting.
Единственный способ получить результат для вашего конкретного случая-это проверить его вручную.
Это наверняка зависит от компилятора и системы. Но нет нужды гадать. Вы можете просто скомпилировать и попробовать
#include <stdio.h> int main() { struct { int n; char c; } A[10][10]; printf("%08x\n", &A[0][0]); printf("%08x\n", &A[0][1]); printf("%08x\n", &A[1][0]); ... printf("%08x\n", &A[3][7]); ... }
Нотация массива-это просто сокращение для вычисления адреса элемента и разыменования его, например:
Вот почему вы не можете использовать n-мерный массив, не зная всего, кроме последнего измерения - компилятор не будет знать, какое смещение добавить к нему, чтобы вычислить адрес.int a[5][15]; Address of a[3][7]: &a + 3 * 15 * sizeof(int) + 7 * sizeof(int)
В этом случае дело осложняется тем, что вы используете структуру. Существует проблема выравнивания, когда структуры дополняются компилятором для выравнивания по слову границы. В этом случае, поскольку сама структура занимает 5 байт, а следующая граница слова будет равна 8 байтам, компилятор, вероятно, добавит 3 неиспользуемых байта к структуре, чтобы компенсировать разницу. (Есть преимущества в производительности, чтобы делать так.) Конечно, это не гарантируется вообще, и вы можете вручную указать, как компилятор должен обрабатывать такие ситуации.
Примечание: как утверждали другие, это очень зависит от системы и компилятора, поэтому не принимайте ничего из этого как Евангелие-попробуйте сами, чтобы быть абсолютно уверенными, каковы будут результаты в вашем случае.
Она полностью зависит от системы, а не от языка .
Также все 2-D , 3-D и так далее массивы фактически распределяются последовательным образом,потому что память является последовательной
(0X00000000 to 0xFFFFFFFF)
Такой 2-D памяти нет или около того .Это полностью зависит от системы, как распределяется память, является ли она
row
Главной илиcolumn
главнойФормула для строки major:
&A[3][7] == &A[0][0] + (3 * 10 * sizeof(struct s)) + (7 * sizeof(struct s))
Для главной колонки:
&A[3][7] == &A[0][0] + (7 * 10 * sizeof(struct s)) + (3 * sizeof(struct s))
И компилятор оптимизировать его структуру заполнения более быстрый доступ по процессору.
Таким образом, для одного объекта размер структуры будет
8
, а не5
(если int имеет размер 4 байта)