попробуйте сами и посмотрите
Отправная точка: так. c
#define THIS_INTEGER 100
int newVariable = THIS_INTEGER;
void fun0 ( void )
{
static int hello;
hello = 100;
}
int fun1 ( void )
{
int hello;
hello = 100;
return(hello);
}
препроцессор выполняет поиск и заменяет определения
arm-none-eabi-gcc -save-temps -O2 -c so.c -o so.o
so.i
# 1 "so.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "so.c"
int newVariable = 100;
void fun0 ( void )
{
static int hello;
hello = 100;
}
int fun1 ( void )
{
int hello;
hello = 100;
return(hello);
}
Вы можете видеть, что THIS_INTEGER больше не существует, это был просто макрос / определить его целью является сохранение в этом случае тракта константы, так что если вы хотите изменить его, вы может изменить все соответствующие экземпляры этого. Но компилятору нужно что-то, что он может на самом деле скомпилировать.
Выход препроцессора so.i затем передается фактическому компилятору, который производит сборку: so.s
.cpu arm7tdmi
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 2
.eabi_attribute 34, 0
.eabi_attribute 18, 4
.file "so.c"
.text
.align 2
.global fun0
.arch armv4t
.syntax unified
.arm
.fpu softvfp
.type fun0, %function
fun0:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
bx lr
.size fun0, .-fun0
.align 2
.global fun1
.syntax unified
.arm
.fpu softvfp
.type fun1, %function
fun1:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
mov r0, #100
bx lr
.size fun1, .-fun1
.global newVariable
.data
.align 2
.type newVariable, %object
.size newVariable, 4
newVariable:
.word 100
.ident "GCC: (GNU) 9.2.0"
То, что передается в ассемблер, а затем, если вы разберете это, вы получите:
Disassembly of section .text:
00000000 <fun0>:
0: e12fff1e bx lr
00000004 <fun1>:
4: e3a00064 mov r0, #100 ; 0x64
8: e12fff1e bx lr
Disassembly of section .data:
00000000 <newVariable>:
0: 00000064
Эхх, я надеялся, что stati c сохранит его там. Для инициализируемой глобальной переменной это делает .data, если это не было бы .bss. Затем в .data вы можете увидеть 100 (0x64). но это не имеет ничего общего с макросом / определение макроса / определение, просто поместите фактическое значение 100 в фактический скомпилированный код.
Для другого случая, с оптимизацией, в стеке нет переменной или что-либо подобное этому значению помещается в регистр возврата, поэтому в этом случае оно ненадолго живет в регистре.
Если бы stati c работал так, как хотелось бы, что в ретроспективе имеет смысл, что нет. Я надеялся на то, что я называю локальным глобальным. Это локальная переменная, но добавление stati c помещает ее в .bss или .data, а не в стек, а затем надеется увидеть сгенерированный код, который затем помещает 100 в переменную, а затем помещает ее в эту область .data / .bss, которая работает неоптимизированной конечно, но это сложнее читать:
Disassembly of section .text:
00000000 <fun0>:
0: e52db004 push {r11} ; (str r11, [sp, #-4]!)
4: e28db000 add r11, sp, #0
8: e59f3018 ldr r3, [pc, #24] ; 28 <fun0+0x28>
c: e3a02064 mov r2, #100 ; 0x64
10: e5832000 str r2, [r3]
14: e1a00000 nop ; (mov r0, r0)
18: e1a00003 mov r0, r3
1c: e28bd000 add sp, r11, #0
20: e49db004 pop {r11} ; (ldr r11, [sp], #4)
24: e12fff1e bx lr
28: 00000000 andeq r0, r0, r0
0000002c <fun1>:
2c: e52db004 push {r11} ; (str r11, [sp, #-4]!)
30: e28db000 add r11, sp, #0
34: e24dd00c sub sp, sp, #12
38: e3a03064 mov r3, #100 ; 0x64
3c: e50b3008 str r3, [r11, #-8]
40: e51b3008 ldr r3, [r11, #-8]
44: e1a00003 mov r0, r3
48: e28bd000 add sp, r11, #0
4c: e49db004 pop {r11} ; (ldr r11, [sp], #4)
50: e12fff1e bx lr
Disassembly of section .data:
00000000 <newVariable>:
0: 00000064 andeq r0, r0, r4, rrx
Disassembly of section .bss:
00000000 <hello.4142>:
0: 00000000 andeq r0, r0, r0
В частности:
c: e3a02064 mov r2, #100 ; 0x64
10: e5832000 str r2, [r3]
100 записывается в регистр, затем это значение регистра записывается в память, где локальный глобальный привет поскольку fun0 живет в .bss.
макросах / определяет просто поиск и замену, препроцессор будет повторять столько раз, сколько необходимо для различных уровней / слоев макросов, пока все они не будут заменены, ни один из них не существует как написано в предварительно обработанном коде. Затем это отправляется компилятору.
ЗНАЧЕНИЕ 100 в этом случае видно в конечном выводе, но это зависит от того, как вы его использовали, как оно представлено или где оно хранится.