Почему делает станд.:: суд преобразовывает энергозависимые указатели на bool?

При попытке ухаживать за указателем на энергозависимый тип, даже энергозависимым символьным указателем, где Вы обычно ожидали бы, что суд распечатает строку, Вы вместо этого просто доберетесь '1' (предположение, что указатель не является нулевым, я думаю). Я принимаю оператор потока вывода <<, шаблон специализирован для энергозависимых указателей, но мой вопрос, почему? Какой вариант использования мотивирует это поведение?

Пример кода:

#include <iostream>
#include <cstring>

int main()
{
    char x[500];
    std::strcpy(x, "Hello world");

    int y;
    int *z = &y;

    std::cout << x << std::endl;
    std::cout << (char volatile*)x << std::endl;

    std::cout << z << std::endl;
    std::cout << (int volatile*)z << std::endl;

    return 0;
}

Вывод:

Hello world
1
0x8046b6c
1
16
задан Joseph Garvin 23 March 2010 в 18:04
поделиться

4 ответа

ostream :: operator << , среди прочего, содержит следующие перегрузки :

ostream& operator<< (bool val );
ostream& operator<< (const void* val );

Когда вы передаете изменчивый указатель, вторая перегрузка не может применяться, потому что изменчивые указатели не могут быть преобразованы в энергонезависимые без явного приведения. Однако любой указатель может быть преобразован в bool, поэтому выбирается первая перегрузка, и вы видите результат 1 или 0.

Таким образом, настоящая причина этого - не намеренное решение от имени комитета по стандартам, а просто что в стандарте не указана перегрузка, которая принимает изменчивый указатель.

28
ответ дан 30 November 2019 в 16:49
поделиться

Я думаю, причина в том, что изменчивые указатели не могут быть неявно преобразованы в void *. Это содержится в Приложении C к Стандарту, и его обоснование - безопасность типа.

Изменение: только указатели на неконстантные и энергонезависимые объекты могут быть неявно преобразованы в void * Обоснование: это повышает безопасность типов.

Таким образом, вместо преобразования в void * (которое будет выводиться в шестнадцатеричном формате) вы получите преобразование по умолчанию в bool.

5
ответ дан 30 November 2019 в 16:49
поделиться

Не ответ

Это просто проблема с формулировкой вопроса и ответами. Проблема возникает из-за невозможности преобразовать указатели на изменчивые объекты в пустые указатели, а не энергозависимые указатели .

Разница, которая довольно важна, заключается в том, какой элемент памяти является энергозависимым. В этом вопросе указатель не является изменчивым (его можно кэшировать, и его не нужно сбрасывать в память при его изменении), а скорее указанная память:

int volatile * p = f();
p++;      // this does not affect the perceived state of the c++ memory model
++p;
*p = 5;   // this changes the perceived state

Причина, по которой это важно, заключается в том, что с volatile указатель на память, сам указатель имеет особую обработку.

void foo( int * );

int * volatile p = f();  // 1
foo(p);                  // 2
int volatile * q = f();
//foo(q);    // error, cannot convert pointer to volatile to pointer to non-volatile
*q = 5;                  // 3
q = 0;                   // 4

В приведенном выше коде операции, отмеченные как 1 и 2, сохраняются в памяти. Присвоение в [1] должно быть выгружено в память. Даже если значение p находится в регистре, оно будет загружено из памяти в [2].Операция с меткой [3] изменяет значение, указанное q , которое является энергозависимым и будет перемещаться в основную память, в то время как операция [4] влияет только на указатель, который not volatile сам по себе, и как таковой не является частью воспринимаемого состояния модели памяти C ++ и может выполняться в регистрах (обратите внимание, что компилятор может оптимизировать q и выполнять операции в регистр, а p не может быть оптимизирован.

2
ответ дан 30 November 2019 в 16:49
поделиться

Я думаю, проблема не в явной перегрузке указателей на изменчивые типы, а в ОТСУТСТВИИ перегрузки указателей на изменчивые типы. Компилятор не может неявно удалить квалификатор volatile из указателей, поэтому он проверяет доступные перегрузки, выбирает bool-версию operator << и преобразует указатель в volatile в bool.

1
ответ дан 30 November 2019 в 16:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: