Как массивы C представлены в памяти?

Мне кажется, я понимаю, как обычные переменные и указатели представлены в памяти, если вы используете C.

Например, легко понять, что указатель Ptr будет иметь адрес, а его значение будет быть другим адресом, то есть пространством в памяти, на которое он указывает. Следующий код:

int main(){
    int x = 10;
    int *Ptr;
    Ptr = &x;
return 0;
}

Будет иметь следующее представление в памяти:

+---------------------+-------------+---------+
| Variable Name       | Address     | Value   | 
+---------------------+-------------+---------+
| x                   | 3342        | 10      |
+---------------------+-------------+---------+
| Ptr                 | 5466        | 3342    |
+---------------------+-------------+---------+

Однако мне трудно понять, как массивы представлены в памяти. Например, код:

int main(){
    int x[5];
        x[0]=12;
        x[1]=13;
        x[2]=14;

    printf("%p\n",(void*)x);
    printf("%p\n",(void*)&x);

return 0;
}

выводит один и тот же адрес дважды (для простоты 10568). Это означает, что x == & x. Тем не менее, * x (или x [0] в обозначении массива) равно 12, * (x + 1) (или x [1] в обозначении массива) равно 13 и так далее. Как это можно представить? Один из способов может быть таким:

+---------------------+-------------+----------+----------------------+
| Variable Name       | Address     | Value    | Value IF array       |
+---------------------+-------------+----------+----------------------+
| x                   | 10568       | 10568    | 12                   |
+---------------------+-------------+----------+----------------------+
|                     | 10572       |          | 13                   | 
+---------------------+-------------+----------+----------------------+
|                     | 10576       |          | 14                   | 
+---------------------+-------------+----------+----------------------+
|                     | 10580       |          | trash                | 
+---------------------+-------------+----------+----------------------+
|                     | 10584       |          | trash                | 
+---------------------+-------------+----------+----------------------+

Это близко к тому, что происходит, или полностью отключено?

26
задан Mankarse 21 October 2011 в 02:12
поделиться

3 ответа

Массив - это блок смежных объектов без пробелов между ними. Это означает, что x в вашем втором примере представлена ​​в памяти как:

+---------------------+-------------+---------+
| Variable Name       | Address     | Value   | 
+---------------------+-------------+---------+
| x                   | 10568       | 12      |
|                     |             +---------+
|                     |             | 13      |
|                     |             +---------+
|                     |             | 14      |
|                     |             +---------+
|                     |             | ??      |
|                     |             +---------+
|                     |             | ??      |
+---------------------+-------------+---------+

То есть, x имеет размер пять int и имеет один адрес.

Странная часть массива не в том, как они хранятся, а в том, как они оцениваются в выражениях. Если вы используете имя массива где-то, что оно не является объектом унарных операторов & или sizeof, оно вычисляется по адресу его первого члена.

То есть, если вы просто напишите x, вы получите значение 10568 с типом int *.

Если, с другой стороны, вы пишете &x, то специальное правило не применяется - поэтому оператор & работает как обычно, что означает, что он выбирает адрес массива. В этом примере это будет значение 10568 с типом int (*)[5].

Причина, по которой x == &x состоит в том, что адрес первого члена массива обязательно равен адресу самого массива, поскольку массив начинается с его первого члена.

33
ответ дан 28 November 2019 в 06:52
поделиться

Массив C - это просто блок памяти, который имеет последовательные значения одинакового размера. Когда вы вызываете malloc (), он просто предоставляет вам блок памяти. foo[5] совпадает с *(foo + 5).

Пример - foo.c:

#include <stdio.h>

int main(void)
{
    int foo[5];
    printf("&foo[0]: %tx\n", &foo[0]);
    printf("foo: %tx\n\n", foo);
    printf("&foo[3]: %tx\n", &foo[3]);
    printf("foo: %tx\n", foo + 3);
}

Вывод:

$ ./foo
&foo[0]: 5fbff5a4
foo: 5fbff5a4

&foo[3]: 5fbff5b0
foo: 5fbff5b0
0
ответ дан 28 November 2019 в 06:52
поделиться

int x [] выдает тот же результат, что и int * x;

это просто указатель

, поэтому обозначения x [i] и * (x + i) ) дают тот же результат.

-1
ответ дан 28 November 2019 в 06:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: