2013-09-11 3 views
1

Я написал этот небольшой код, чтобы проверить свое понимание. Но не понял некоторых фактов. Я работаю над 64-разрядной мини-машиной. Таким образом, любой указатель имеет 8 байтов. Это означает, чтоtypecasting in c между типами данных

#include<stdio.h> 
int main(){ 
    char *c = (char *)0x12345678889; 
    long a = 1; 
    int b = (long)(c-a); 
    /* int cc = (int)(c-a); gives compiler error */ 
    printf("val = %x and b = %x", c-a,b); 
    return 0; 
} 
Output 
val = 45678888 and b = 45678888 

Произнесите стартовый адрес 100. Таким образом, char* будет храниться в памяти как 100-> 89, 101-> 88 ... 105-> 12 и байт 106 и 107 будет использоваться. Является ли это предположение моим правильным в первую очередь? Поскольку int и long составляют 4 байта на 64-битной машине, она начнется с 100,101,102 и 103 и рассмотрит только эти байты. Итак, 45678889 - 1 = 45678888. Правильно ли я понимаю? И, наконец, я не понимаю, в то время как прокомментированная строка дает ошибку компилятора. Компилятор неявно приписывал указанную выше строку. Но почему не ниже?

+2

«int и long 4 байта в 64-битной машине» - необязательно. По моему, 'sizeof (long) == 8'. –

+0

«char *» - это адрес, который на большинстве машин равен «4 байтам», поэтому «char * c = (char *) 0x12345678889;' не имеет смысла. Я считаю, что компилятор проигнорирует отставание '889'. –

+1

Кроме того, если у вас есть достойный компилятор, вы получите объяснение об ошибке. Мой GCC говорит «отбрасывается из указателя в целое число разного размера», что довольно описательно. –

ответ

1

Сначала вы не знали априорно, как хранятся значения, это зависит от машины endianess. Значения могут храниться от младших до высших цифр или в обратном порядке. У вас от низкого до высокого.

Во-вторых, на многих 64-битных машинах int длиной 4 байта и длиной 8 байтов. Что происходит, так это то, что ваша машина вычисляет c-a, которая равна 0x12345678888 типа (char *), затем преобразует ее в long со значением 0x12345678888, а затем усекает его молча (длинные молчания преобразуются в ints в C).

Комментарий дает предупреждение, потому что c-a имеет тип char * и которые не могут быть автоматически конвертируют в int (считается очень опасным данс долго, чтобы ИНТ). Хорошо, тогда вы его явно преобразили, но компилятор предупреждает вас, что это тоже опасно. Обратите внимание, что это предупреждения, а не ошибки (это может зависеть от параметров компилятора ...).

+0

Почему нужно долго молчать с помощью int? Длинные 8 байт вправо. Почему компилятор не сохраняет все 8 байтов в длинной переменной – CHID

+0

Именно так определяется C. longs можно назначить ints. В этом случае назначение усекает значение до младших байтов (здесь самые низкие 4 байта 0x45678888). Компилятор сохраняет значение в длинной переменной (временную), но вы назначили ее int. –

+1

@AndreyT Нет 'c-a' правильно! Это арифметика указателя, которая хорошо определена в C. Она вычисляет новые значения указателя относительно заданного. Он возвращает «a» назад из указателя 'c'. Как 'c' в' char * ', длина шага - это длина' char'. –

Смежные вопросы