Правильность «свободной» функции в K & R - PullRequest
2 голосов
/ 25 апреля 2019

В главе Арифметика адресов функция afree определяется следующим образом:

static char allocbuf[ALLOCSIZE]; // storage for alloc
static char *allocp = allocbuf;  // next free position

void afree(char *p) 
{
    if (p >= allocbuf && p < allocbuf + ALLOCSIZE)
        allocp = p;
}

Насколько я вижу, смысл оператора if в том, чтобы проверить, находится ли p в пределах буфера.

Однако, если p находится за пределами буфера, сравнение приводит к неопределенному поведению, не так ли? Разве нет необходимости преобразовывать оба указателя (p и allocbuf) в целые числа перед выполнением сравнения?

Должна ли функция выглядеть не так или эта версия вообще неверна?

void afree(char *p) 
{
    uintptr_t p_int = (uintptr_t) p;
    uintptr_t a_start = (uintptr_t) allocbuf;
    uintptr_t a_end = (uintptr_t) (allocbuf + ALLOCSIZE);

    if (p_int >= a_start && p_int < a_end)
        allocp = p;
}

1 Ответ

1 голос
/ 25 апреля 2019

Однако, если p находится за пределами буфера, сравнение приводит к неопределенному поведению, не так ли?

Да.

Разве нет необходимости преобразовывать оба указателя (p и allocbuf) в целые числа перед выполнением сравнения?

Да, это обычная работа.

Несмотря на это, арифметические отношения >, < и некоторых == не указываются для таких преобразованных указателей. Ваш обновленный код по-прежнему не работает должным образом, но результат, по крайней мере, не UB.

Учтите, что два указателя int_street:1 и char_street:4 могут указывать на один и тот же физический адрес и сравнивать их, как указатели, но целые числа 0x00010004, 0x00020004 различны.


Обратите внимание, что K & R было написано давно, даже до Долгое время назад в Галактике Далеко , когда (u)intptr_t не было определено.

C99 запущен (u)intptr_t. Они остаются необязательными типами, даже если они очень часто используются.

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