2015-01-08 4 views
1

Может ли кто-нибудь помочь мне лучше понять, как работает распределение памяти? Я был бы признателен, если кто-то может пройти шаг за шагом (надеюсь, с картинками), что происходит в этом коде:Что делает этот код? Распределение памяти

char a[3][4] = {"xy", "abcd", "!?"}; 
char (*b)[4], *c; 
b = a + 1; 
c = *a + 1; 

я посмотрел вокруг, но не нашел ничего объяснить это тщательно, спасибо!

Edit: Я был бы признателен, если кто-то может объяснить это с помощью memoryblocks, ех, [х] [у] [] [а] [б] [с] [d] []

+1

Считается, что он ничего не делает, поскольку он не имеет побочных эффектов ... – unwind

+1

Должен быть увеличенный размер строки «abcd», * пять символов длиной, включая терминатор, набитый в нижний * четыре * -char массив должен учитываться в любых ответах? – WhozCraig

+1

@WhozCraig Нет, это не проблема. 'char foo [3] =" foo ";' является корректным и не добавляется терминатор, если литерал - это точно длина массива. – unwind

ответ

2
char a[3][4] = {"xy", "abcd", "!?"}; 

Первая команда выделяет матрицу 3 на 4 в стеке и инициализирует элементы двумерного массива некоторыми символами.

char (*b)[4], *c; 

Запасяет указатель на массив символов размером 4 имени b в стеке. Кроме того, он создает второй указатель char с именем c.

b = a + 1; 

Вы хранить в указатель б начальный адрес массива а + 1, что означает, что адрес второго элемента (вторая строка из 4-х символов).

c = *a + 1; 

Вы разыменования, производя указатель на первый элемент (элемент а является массив символов размером 4), и добавить 1 к этому указателю - вот вторую букву первой записи.

+2

* Сохраняет указатель char с именем b в стеке 4 элемента с 4 элементами *: Что это значит? – haccks

+1

'b' на самом деле является« указателем на массив из 4 символов ». Я не на 100% положителен, но думаю, что sizeof (* b) будет 4, а не 1. – Arkadiy

+0

@Arkadiy; Да. Ты прав. – haccks

1
#include <stdio.h> 

int main(int argc, char *argv[]) 
{ 
    // the second dimension should 5 
    // since "abcd" is 4 chars + null terminator 
    char a[3][5] = {"xy", "abcd", "!?"}; 
    char (*b)[5], *c; 
    b = a + 1; 
    c = *a + 1; 

    // b = a + 1, thus it points to the second entry of a array 
    printf("%s\n", b[0]); 

    // c = *a + 1, thus it points where a points to, plus one, 
    // thus in the second letter of a's first entry 
    printf("%c\n", *c); 
    return 0; 
} 

EDIT о вашем редактировании

a -> [x][y][0][0][0][a][b][c][d][0][!][?][0][0][0] 
b -> [a][b][c][d][0][!][?][0][0][0] 
c -> [y] 

С нулями Я представляю нулевой ограничитель. Обратите внимание, что в вашем примере не так уж важно иметь его, но я думаю, что всегда хорошо иметь нулевые строки в C. Поэтому я немного изменил ваш код.

Почему не только 1 нулевой ограничитель на строку в a? См. this ответ.

+0

Нулевые терминаторы не должны быть только 1, после. Пример: [x] [y] [\ 0] [] [] [a] .. – Fjondor

+0

№ @Fjondor, так как вы используете список инициализаций там, все пустые ячейки будут инициализированы нулями. – gsamaras

+0

@Fjondor Я включил ссылку, которая могла бы помочь. Помогло ли объяснение скобки? – gsamaras

0

Переменная a представляет собой массив массивов char. Переменная b является указателем на массив из char, c является указателем на символ.

Переменная a инициализируется при объявлении. Затем переменной b присваивается значение второй массив a (то есть a[1]), а c назначается второй букве a[0].

Что касается назначения b, выражения a[1] и *(a + 1) эквивалентны.

Для присвоения c, a сам по себе является указателем на первый элемент массива, т.е. это указатель a[0] (a такое же, как &a[0]). При разыменовании a вы получаете первую запись a, то есть вы получаете a[0]. Добавляя один к a[0], вы получите второй символ a[0], то есть a[0][1].