Размер пустоты - PullRequest
       11

Размер пустоты

1 голос
/ 24 марта 2012

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

sizeof(char)

не всегда 1 байт, а как насчет void *?Если я сделаю

void *p
++p

, будет ли он указывать везде на один байт дальше?

Ответы [ 3 ]

8 голосов
/ 24 марта 2012

В C арифметика указателей не определена для пустых указателей . Арифметика указателя неразрывно связана с размером указанного типа. А для void * размер указанного типа неизвестен.

Чтобы увидеть, как работает арифметика указателей для разных объектов, попробуйте следующее:

int obj[5];
int *ip = obj;
char *cp = (char *)obj;

ip++;
cp++;

printf("%p\n%p\n", ip, cp);

Однако, если компилятор его поддерживает, арифметика указателей на указателях void работает так же, как и на указателях символов.

1 голос
/ 24 марта 2012

По определению, char занимает один байт памяти, поэтому, если вы хотите выполнить вычисления адреса на основе размеров байтов, используйте char *.В то время как стандарт C требует, чтобы void * имел то же представление, что и char *, void * не несет информации о размере и поэтому не может использоваться для арифметики указателей.

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

Теперь, комментарий к ответ Джонатона :

В то время как целочисленные типы фиксированной ширины из stdint.h также не содержат отступов, и вы можете использовать их, как описано для определенных архитектур (нет ничего плохого в коде для конкретной платформы, если вам не нужно быть переносимым), вВ общем, вы знаете только их ширину в битах, а не их размеры в байтах, поскольку CHAR_BIT может отличаться от 8 (16 и 32 являются «общими» для некоторых частей встроенного мира).Тем не менее, байт == октет требуется для систем POSIX.

Целочисленные типы фиксированной ширины определенных размеров не должны существовать: в частности, если CHAR_BIT не является степенью 2 (да,такие архитектуры существуют), ни один из типов uint8_t, uint16_t, uint32_t, uint64_t не может существовать

1 голос
/ 24 марта 2012

Для этого, я думаю, вы должны использовать <stdint.h>.Он определяет следующие типы (среди прочих):

uint8_t   Always 1 byte (assuming 8-bit bytes, as is nearly ubiquitous)
uint16_t  Always 2 bytes
uint32_t  Always 4 bytes
uint64_t  Always 8 bytes

Если вы знаете, что делаете, и хотите арифметически ориентироваться в памяти, то делайте это с помощью указателя uint8_t*.(Да, я просто использовал это как глагол, кстати.)

Пример:

uint8_t* p = <Some Base Addr>;
while (*p)   // p points to non-null byte
{
    *p ^= 0xA5;   // XOR the byte with A5
    p++;          // Increment to the next byte.

    *(uint32_t*)p = 0xDEADBEEF;  // Write a 32-bit (DWORD)
    ((uint32_t*)p)++;            // Increment p by 4 bytes
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...