2016-01-13 4 views
-4

Я написал следующий Кодекс.Как распределяется память для переменных разных типов данных?

#include<stdio.h> 

int main() 
{ 
    int x = 1 ; 
    int *j = &x ; 
    int y = 2 ; 
    int *t = &y ; 

    printf("%p\n" , (void *)j); 
    printf("%p" , (void *)t); 
} 

Выход 0028FF14 0028FF10.

Точка, которую я хочу сделать, заключается в том, что разница между адресами равна «4».

В то время как в этом случае

#include<stdio.h> 

int main() 
{ 
    char x = 't' ; 
    char *j = &x ; 
    char y = 'f' ; 
    char *t = &y ; 
    printf("%p\n" , (void *)j); 
    printf("%p" , (void *)t);  

    } 

Выход 0028FF17 0028FF16

Разница заключается в 1.

Разница в первом случае - 4. Если во втором случае это 1. Почему это так?

И что я получу, если бы напечатал значение по всем адресам памяти по отдельности?

Возможно, это действительно общий и известный, но я только начал C, поэтому вывод программы смущает меня.

Update
Теперь, используя формат %p и преобразуется значение указателя на void* напечатать значение указателя, как предложено Keith Thompson.

+1

@SergeyK .: Нет, я не думаю, что это дубликат. Никакой указатель не увеличивается. Код просто рассматривает адреса объявленных объектов. –

+0

@ KeithThompson Тем не менее, базовый механизм тот же, и объяснение полностью применимо к этому делу. –

+3

@ Серый К .: Я не согласен. Для 'указателя ++' отношение корректно определено. Между адресами двух отдельно определенных объектов нет определенной связи. Адреса 'char x;' и 'char y;' могут легко отличаться на 4, например, или на 42. –

ответ

3

Нет требований к порядку размещения объявленных объектов в памяти. По-видимому, используемый вами компилятор размещает x и y рядом друг с другом. Это могло уложить j между ними, но это не произошло.

Кроме того, правильный способом печати значения указателя является использование формата %p и преобразовать значение указателя на void*:

printf("%p\n", (void*)j); 
printf("%p\n", (void*)t); 

Это создает определенную реализацию удобочитаемого представления значения указателя, обычно, но не всегда в шестнадцатеричной форме.

Если у вас ухаживание о заказе, в котором объявленные переменные выделены в памяти, вы, вероятно, делаете что-то неправильно или, по крайней мере, не полезно. Пусть компилятор беспокоится о том, куда положить вещи. Он знает, что он делает.

+0

Я не уверен, что вы подразумеваете под этим. Объект 'char' выделяется ровно 1 байт. Объекту 'int' присваивается' sizeof (int) 'bytes. Объекты могут быть выделены в любом порядке, и между ними может быть или не быть дополнительное дополнение. –

+1

Я не понимаю, что вы имеете в виду. Адрес типа 'int *' относится к местоположению объекта 'int'. Этот объект занимает 'sizeof (int)' байт, обычно 4. Но когда вы печатаете значение указателя, он обычно отражает адрес первого байта объекта, на который он указывает. Есть ли какая-то конкретная проблема, которую вы пытаетесь решить здесь? На мой взгляд, ваш вопрос не дублируется. –

+0

@SurajJain: Конечно, указатель на N-байтовый тип укажет на объект N-байта. –

2

Ну, для начала разница не всегда четыре, это просто бывает счастливым совпадением. Компилятору разрешено вставлять переменные в память, где бы он ни захотел. В этом случае он помещает ваши две переменные рядом друг с другом в память, и разницу можно объяснить, так как это то, как большое целое число находится в вашей системе (4 байта) и как большой символ находится в вашей системе (1 байт). В других системах они могут быть разных размеров и размещаться в разных местах.

1

Каждое целое число занимает четыре байта, поэтому каждый целочисленный адрес памяти смещается на 4. Символ принимает только один байт, поэтому его адреса памяти смещены на один.

+0

Что произойдет, если я напечатаю значение по адресам, которые находятся между ними? –

+0

Вы получите индивидуальные байты, составляющие номер. Например, если значение int равно 1, тогда он будет 0x00000001 в шестнадцатеричном виде, который разбился бы на следующий массив символов 0x00,0x00,0x00,0x01. –