2013-02-27 3 views
1

Я просматриваю код C и хочу знать, правильно ли я понял код.Тип Указатель на литье в C

Существует структура, BF_salt определена в заголовочном файле, как показано ниже:

typedef 
{ 
BF_WORD salt[4]; 
.. 
.. 
} BF_SALT; 

В основном C Кодекса, есть вызов функции:

function func1() 
{ 
static BF_SALT salt; 
func2(salt.salt,x,y); 
.... 
} 

func2(BF_WORD * dst,x,y) 
{ 
unsigned char * dptr= (unsigned char*)dst; 
int c1,c2; 

// c1 and c2 are initialized here. 

// in a loop, an operation similar to the below is performed. 

*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4); 
} 

Мое понимание приведенный выше код:

в func1, соль определяется с типом данных структуры BF_SALT.

Мы вызываем func2, передавая соленое поле структуры.

поле соль представляет собой массив из 4 элементов, каждый из типов данных BF_WORD (32 битного слова или 4 байта)

в func2

целевой_адрес это имя массива, который указывает на элемент тип BF_WORD.

Выполняет это приведение по указа + ст.

В настоящее время dst указывает на тип данных BF_WORD. это тип casted, так что он указывает на char (1 байт данных).

теперь он выполняет операции битбой по целым числам c1 и c2 и записывает вывод в адрес памяти, указанный dptr. Таким образом, это переписывание данных, на которые первоначально указывалось dst (байты в массиве солей).

c1 и c2 имеют тип данных int, что требует 4 байтов пространства.

Каким образом dptr перезапишет содержимое массива? Поскольку каждый раз мы делаем * dptr ++, мы продвигаем указатель, dptr на 1 байт, потому что он указывает на символ.

Однако мы присваиваем ему значение размером более 1 байт. Как данные будут записаны в память?

Спасибо.

ответ

0

Ваше понимание кода выше, является похож на мой, а также позвольте мне чип в некоторых из моих собственных мыслей

unsigned char * dptr= (unsigned char*)dst; 

Здесь DST, который имеет тип BF_WORD (4 байта), с понижением с приведением к a char type (1 байт) Также стоит отметить, что хотя тип указателя является char и может перемещаться по по одному байту за раз, он хранит адрес 4-байтового смежного местоположения памяти, , так что технически он должно быть умело перемещать эти 4 байта, байт за раз.

Каким образом dptr будет перезаписывать содержимое массива?

dptr теперь содержит начальный адрес 4-х цифр, 4 байтовых массива. Таким образом, в настоящее время он получает доступ к соли [0]. Здесь соль [0] имеет размер 4 байта, а dptr - 1 байтовый указатель, поэтому для покрытия одного элемента массива [0] требуется четыре (dptr ++) приращений.

Теперь другой вопрос

мы присваиваем ему значение размера больше 1 байта. Как данные будут записаны в память?

*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4); 

Здесь и c1 и c2 типа Int, поэтому после операции побитовое результат типа междунар. Следовательно, результат 4 байта записывается в соль [0], на которую указывает dptr; В следующем приращении dptr указатель укажет на 2 байта предыдущего 4 байта , поэтому последние три байта предыдущего результата будут превышены следующим поразрядным результатом.

+0

"* Следовательно, результат 4 байта записывается в соль [0], на которую указывает dptr ... *", но только младший байт присваивается тому, что указывает 'dptr', так как это' unsigned char * '! И: Какой «* ... следующий побитовый результат. *», Пожалуйста? Я не вижу петли. – alk

+0

@alk Да, я подумал об этом, младший байт назначен, если его неявно typecasted и, следовательно, более высокие 3 байта усечены, , но я думаю, что неявное typecasting occours только, если назначение левой руки является переменной типа данных, а не указателем , Поправьте меня, если я ошибаюсь –

+0

Слева находится ** указатель ** разыменованный **. Пожалуйста, см. Ответ * Leushenko *, так как он был так добр, чтобы найти стандарт. – alk

1

Здесь

*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4); 

неявное приведение к unsigned char выполняется, так как dptr имеет тип unsigned char *, поэтому *dptr рассматривается как unsigned char.

+0

Спасибо. Да, операция инкремента выполняется по указателю, потому что есть цикл, хотя я не упоминал об этом. Я отредактировал сообщение, чтобы показать, что существует цикл. –

+0

@NeonFlash: Я вижу, так обновляю свой ответ. – alk

2

Только младший байт результата будет записан в память. Поскольку указатель относится к char, int будет усечен и высшие байты будут потеряны, поскольку он преобразуется в тип lvalue; то же правило, как если бы вы просто присвоили результат переменной char. Подробные сведения см. В стандартных разделах 6.3.2.1 и 6.5.16.1.

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