Каковы возможные значения для действительного указателя? - PullRequest
0 голосов
/ 23 января 2019

Стандарт ограничивает возможные адреса памяти (которые я бы интерпретировал как возможные значения для указателя)?Может ли ваш код полагаться на некоторые значения, которые никогда не будут использоваться и все еще будут полностью переносимыми?

Я только что видел это в нашей базе кода (это библиотека C), и мне было интересно, будет ли это всегда нормально.Я не уверен, что автор имел в виду под этим, но это, очевидно, не просто проверка на возможное значение NULL.

int LOG(const char* func, const char* file,
                 int lineno, severity level, const char* msg)
{
    const unsigned long u_func = (unsigned long)func;
    const unsigned long u_file = (unsigned long)file;
    const unsigned long u_msg   = (unsigned long)msg;

    if(u_func < 0x400 || u_file < 0x400 || u_msg  < 0x400 ||
       (unsigned)lineno > 10000 || (unsigned)level > LOG_DEBUG)
    {
        fprintf(stderr, "log function called with bad args");
        return -1;
    }
    //...
}

Другой возможный вариант использования этого - хранение логических флагов внутри указателя, а не вотдельная переменная-член в качестве оптимизации.Я думаю, что оптимизация небольших строк в C ++ 11 делает это, но я могу ошибаться.

EDIT:

Если это определяется реализацией, как некоторые из вас упоминали, вы можете обнаружить его во время компиляции?

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Ограничивает ли стандарт возможные адреса памяти (которые я бы интерпретировал как возможные значения для указателя)?

Стандарт C ++ (насколько мне известно) не ограничивает возможную памятьадреса.

Может ли ваш код полагаться на некоторые значения, которые никогда не будут использоваться и по-прежнему будут полностью переносимыми?

Программа, которая безоговорочно полагается на такую ​​реализацию, определенную (или не определеннуюстандартная) деталь не будет полностью переносимой на все конкретные и теоретические стандартные реализации.

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


PS Еще одна вещь, на которую технически нельзя полагаться: unsigned long не гарантирует возможность представлять все значения указателя (uintptr_t is).

0 голосов
/ 23 января 2019

Стандартный термин - «безопасно выведенный указатель».Это определяется реализацией, если вы можете использовать в своей программе небезопасные производные указатели - например, числовые константы.

Вы можете проверить модель безопасности указателя с помощью std::pointer_safety: https://en.cppreference.com/w/cpp/memory/gc/pointer_safety

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