sizeof(long)
обычно определяется компилятором (подверженным базовой архитектуре HW).
sizeof(long*)
подвергается размеру адресного пространства виртуальной памяти на вашей платформе.
Например, с Visual Studio компилятор для 64-разрядной операционной системы и 64-разрядных процессоров:
sizeof(long) == 4
sizeof(long*) == 8
Поэтому:
- С
long b = p
, только 4 наименее значимых байта p
копируются в b
- С
*(long*)b
, вы потенциально пытается получить доступ к недопустимому адресу ПАМЯТЬ
В этом примере, если 4 наиболее значимые байты p
равны нулю, то «никакого вреда не будет сделано». Но так как это не гарантируется, когда sizeof(long) != sizeof(long*)
этот код обычно небезопасен.
В дополнение к этому, даже если sizeof(long) == sizeof(long*)
, вы все равно не должны использовать этот тип конверсий (указатель на целое), чтобы сохранить свой код переносимым на другие платформы.
UPDATE
Пожалуйста, обратите внимание, что printf("%lld\n", *(long*)b)
также небезопасно.
Вы должны в основном использовать "%ld"
для значений long
и "%lld"
для long long
значений.
Если sizeof(long) < sizeof(long long)
, это может привести к нарушению доступа к памяти во время работы.
В стандарте языка такого положения нет, что указатель всегда конвертируется в целое. Это просто совпадение, так как int по какой-то причине долгое время. – AlexanderVX
Этот код должен вызывать предупреждение об использовании указателя как целого без приведения. – user3629249
, если вы разместили этот код в файле и скомпилировали его (с включенными предупреждениями), компилятор поставил бы неправильный код. Тогда не было бы необходимости задавать вопрос – user3629249