кастинг адреса - PullRequest
       1

кастинг адреса

1 голос
/ 08 января 2012

У вас есть операционная система, которая имеет 2 функции, связанные с распределением памяти:

void *malloc( int sz ) // allocates a memory block sz bytes long

void free( void *addr ) // frees a memory block starting at addr
                        //  (previously allocated by malloc)

Используя эти функции, реализуйте следующие 2 функции:

void *malloc_aligned( int sz ) // allocates a memory block sz bytes long,
                               //  aligned to an address divisible by 16

void free_aligned( void *addr )  // frees a memory block starting at addr
                                 // (previously allocated by malloc_aligned)

в решенииследующая часть:

void * aligned_malloc(size_t size){
     unsigned char *res=malloc(size+16);
     unsigned char offest=16-((long)res%16);

Чего я не понимаю, так это: зачем нам использовать unsigned char и почему и чего мы достигаем с помощью 16-((long)res%16); и какова цель (long)res вэто дело?

1 Ответ

3 голосов
/ 08 января 2012

Вы не можете сделать арифметику указателей для "void *", потому что void не имеет размера.
При добавлении или вычитании указателя это всегда выполняется в единицах sizeof(*p). Значение: если вы добавляете единицу к указателю int, его значение увеличивается на 4 (потому что размер целого числа равен 4). Поэтому, когда вы добавляете к пустому указателю, он должен увеличиваться на размер пустого. Но пустота не имеет размера.

Однако, некоторые компиляторы готовы выполнять арифметику на void *, и они относятся к ней как char *. С этими компиляторами вы могли бы реализовать эти функции без приведения. Но это не стандартно.

Другой момент заключается в том, что не все операторы применимы для указателей. Сложение и вычитание есть, но умножение, деление и модуль не. Поэтому, если вы хотите проверить младшие биты указателя, чтобы узнать, выровнен ли он, вы приведете его к длинному.
Почему долго? Предполагается, что long равен указателю, что верно для Linux, но не для Windows. Правильный тип - uintptr_t. Однако, если вас интересуют только младшие биты, не имеет значения, теряете ли вы старшие биты во время чтения. Так что приведение к int тоже сработало бы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...