Лучшее, что можно сделать в подобных ситуациях - это попробовать.Вот пример программы:
int main(int argc, char **argv)
{
int adad=12345;
volatile char character;
character=*((char *)(&adad)+2);
return 0;
}
Я добавил volatile
, чтобы избежать полной оптимизации строки назначения.Теперь вот что придумал компилятор (для -Oz
на моем Mac):
_main:
pushq %rbp
movq %rsp,%rbp
movl $0x00003039,0xf8(%rbp)
movb 0xfa(%rbp),%al
movb %al,0xff(%rbp)
xorl %eax,%eax
leave
ret
Нам нужны только три строки:
movl $0x00003039,0xf8(%rbp)
movb 0xfa(%rbp),%al
movb %al,0xff(%rbp)
movl
это инициализация adad
.Затем, как вы можете видеть, он считывает 3-й байт adad
и сохраняет его обратно в память (volatile
принудительно возвращает это хранилище).
Я думаю, хороший вопрос - почемуВам важно, какая сборка генерируется?Например, просто изменив мой флаг оптимизации на -O0
, вывод ассемблера для интересной части кода будет выглядеть следующим образом:
movl $0x00003039,0xf8(%rbp)
leaq 0xf8(%rbp),%rax
addq $0x02,%rax
movzbl (%rax),%eax
movb %al,0xff(%rbp)
Что довольно просто воспринимается как точные логические операции вашего кода:
- Инициализация
adad
- Взять адрес
adad
- Добавить 2 к этому адресу
- Загрузить один байт, разыменовав новый адрес
- Сохранение одного байта в
character
Различные оптимизации изменят вывод ... если вам действительно нужен какой-то определенный режим поведения / адресации по какой-то причине, вам, возможно, придется написатьсборка самостоятельно.