Как я могу установить нижние 3 байта длиной 4 байта, оставив верхний байт нетронутым? - PullRequest
1 голос
/ 27 ноября 2009

Соответствующий код:

typedef unsigned long int chunk_head;

typedef struct malloc_chunk
{
    // Contains the size of the data in the chunk and the flag byte.
    chunk_head      head;

    // Deliberately left unsized to allow overflow. 
    // Contains the payload of the chunk.
    unsigned int    data[];
};

И в качестве примера, макрос "get" выглядит так:

//Get the size of the data contained within the chunk.
#define GET_CHUNK_SIZE(chunk) ((chunk.head) & 0xFFFFFF)

Старший байт, который я использую для флагов - биты "inuse" и "могут быть объединены", и любые дополнительные, которые я найду, будут полезны.

Теперь, когда я закончил предоставлять справочную информацию, как я указал в заголовке, мне нужно иметь возможность изменить младшие 3 байта на размер блока. Мой первоначальный инстинкт был побитовый И заголовок с размером, так как он был бы правильно выровнен, но потом я понял, что он может также перезаписать байты флага, потому что он автоматически добавляет нули до тех пор, пока его размер не совпадет с длинным. Я даже не уверен, что вы можете поразрядно И int и long. В любом случае, помощь очень ценится.

Ответы [ 6 ]

7 голосов
/ 27 ноября 2009

Как насчет:

head = (head & 0xff000000) | (new_size & 0x00ffffff)
4 голосов
/ 27 ноября 2009

По некоторым причинам большинство ответов, которые вы получили до сих пор, настаивают на том, чтобы скрыть потенциальную проблему переполнения размера под ковром, то есть они "и" размер куска с 0x00FFFFFF, таким образом, незаметно отбрасывая биты чрезмерного размера (если есть) и затем перейдите к записи совершенно бессмысленной хвостовой части размера в поле. Я не знаю, зачем кому-то делать что-то подобное.

Более разумный код может выглядеть следующим образом

assert((size & 0xFF000000) == 0);
chunk.head = (chunk.head & 0xFF000000) | size;

Нет веских причин для "и" размера с 0x00FFFFFF. Вам следует либо прервать, либо хотя бы заявить о чрезмерном размере, но не отказываться от лишнего спокойно.

3 голосов
/ 27 ноября 2009

Используйте битовые поля для этого. Это избавляет от необходимости использовать макросы, что приятно в отладчике:

typedef struct chunk_head {
  unsigned size:24;
  unsigned inuse:1;
  unsigned cancoalesce:1;
  // Room for 6 more...
};

typedef struct malloc_chunk {
  struct chunk_head head;
  int data[];
};
0 голосов
/ 27 ноября 2009
// retain the old top 8 bits
chunk.head &= 0xFF00000000

// set the lower 24 bits
chunk.head |= (0x00FFFFFF & new_bits)
0 голосов
/ 27 ноября 2009
#define SET_CHUNK_SIZE(chunk, size) (chunk.head = (chunk.head & 0xFF000000) | (size & 0x00FFFFFF))

Ты это имел ввиду или я что-то упустил?

0 голосов
/ 27 ноября 2009

chunk.head = (chunk.head & ~0xffffffL) | (new_lower_bits)

...