2015-01-08 3 views
1

У меня есть случай, в котором у меня есть uint64_t*, а char* (6 символов длиной), а также uint16_t*, что указывают на адреса x, x+2 и x соответственно. Поэтому, если char * указывает на «This i», тогда uint16_t* должен указывать на значение 0 dec, а uint64_t* должен указывать на значение 115, 588, 096, 157, 780 dec.Перекрытие Указатели

Но когда я смотрю на эти значения, я получаю 0 деци для uint64_t. Я не понимаю, почему это было бы. Может ли кто-нибудь объяснить?

Edit (добавлен код):

FILE *file = fopen("/Users/Justin/Desktop/test.txt", "rb"); 
uint64_t *window = malloc(8); 
char *buffer = (char*)(window+2); 
uint16_t *data = (uint16_t*)window; 
uint16_t *read = (uint16_t*)(window+6); 

fread(buffer, 6, 1, file); 

printf("%p\n", window); 
printf("%p\n", buffer); 
printf("%p\n", data); 
printf("%p\n", read); 
printf("%s\n", buffer); 
printf("%llu\n", *window); 

и выход:

0x100105440 
0x100105450 
0x100105440 
0x100105470 
This i 
0 
+0

Являются ли ваши символы в ASCII или другом символе UTF. Например, все символы ASCII имеют десятичные значения от 0 до 127; и 588 выходит за пределы диапазона. –

+0

ASCII-символы – JDOdle

+1

Код в 'c'. Почему вопрос помечен 'C++'? – user2079303

ответ

6

Вы получаете подножку по указателю математике.

Как window объявлен как uint64_t *, window + 2 не увеличивает адрес на два байта; он увеличивает его на 2 * sizeof(uint64_t) (т. е. шестнадцать байтов). В результате память, на которую вы смотрите, неинициализирована (и, фактически, лежит вне выделенного блока).

Если вы на самом деле хотите, чтобы адрес был увеличен на два байта, вам нужно привести указатель к char *перед тем добавления 2 к нему:

char *buffer = ((char *) window) + 2; 
+0

Я думал, что отображение адресов mem было битовыми адресами, а не байтами. Спасибо, что поняли это. – JDOdle

2

Я думаю, вы недоразумение, что в +2 делает здесь:

uint64_t *window = malloc(8); 
char *buffer = (char*)(window+2); 

Это помогает визуализировать данные, которые мы получили от malloc, используя |, чтобы помочь показать границы 8-байтовых:

|-------|-------|-------|-------|-------|-------|-------|------- 
^ 
window 

Теперь buffer не указывает два байта впереди window. Он указывает два uint64_t вперед. Или, другими словами, ((char*)window) + 2 * sizeof(*window):

|-------|-------|-------|-------|-------|-------|-------|------- 
^    ^
window   buffer 

который затем Fread в

|-------|-------This i--|-------|-------|-------|-------|------- 
^    ^
window   buffer 

Если вы хотите просто указать два байта вперед, вы должны добавить 2 к char*:

char* buffer = ((char*)window) + 2; 
0

В дополнение к указателям-указателям, которые @duskwuff указал, и @Barry пояснил, есть еще одна проблема. Ответ, который вы получите, будет зависеть от архитектуры компьютера, на которой работает этот код.

На машинах большого конца вы получите один ответ, на машинах с маленькими концами вы получите другой ответ.

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

+0

Или до тех пор, пока это не ошибки страницы, что, вероятно, лучше. –

+0

_Выбор буфера с использованием% s очень опасен _... Может быть, альтернативный способ написать буфер менее опасным способом? – ryyker

+0

Я принимал энтузиазм во внимание при отправке моего вопроса, а% s было просто для быстрого подтверждения. Обычно я этого не делал – JDOdle

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