Korzystanie C oprócz kompilatora, że doskonale wie o rodzaju podanych wartości nie ma systemu że wie o rodzaju danej wartości.
Należy pamiętać, że C sam z siebie nie wprowadza żadnego systemu informacji o typie środowiska wykonawczego.
Spójrz na poniższy przykład:
int i_var;
double d_var;
int main() {
i_var = -23;
d_var = 0.1;
return 0;
}
w kodzie są dwa różne typy wartości zaangażowanych jeden być przechowywane jako liczba całkowita i jeden być przechowywane w postaci podwójnej wartości.
Kompilator, który dokładnie analizuje kod, zna dokładne typy obu z nich. Oto zrzut z krótkiego fragmentu gcc informacyjnego typu odbyła natomiast kod pokolenie generowane przez przepuszczenie -fdump-tree-all
do gcc:
@1 type_decl name: @2 type: @3 srcp: <built-in>:0
chan: @4
@2 identifier_node strg: int lngt: 3
@3 integer_type name: @1 size: @5 algn: 32
prec: 32 sign: signed min : @6
max : @7
...
@5 integer_cst type: @11 low : 32
@6 integer_cst type: @3 high: -1 low : -2147483648
@7 integer_cst type: @3 low : 2147483647
...
@3805 var_decl name: @3810 type: @3 srcp: main.c:3
chan: @3811 size: @5 algn: 32
used: 1
...
@3810 identifier_node strg: i_var lngt: 5
Polowanie dół @links należy wyraźnie zobaczyć, że tam naprawdę jest dużo informacji przechowywanych o rozmiar pamięci, ograniczenia wyrównania i dozwolone wartości min i max dla typu "int" zapisane w węzłach @ 1-3 i @ 5-7. (I pominięte węzeł @ 4 jak wspomniany „chan” wejście jest tylko używana do cha ja n się żadnych definicji typu w wygenerowanym drzewa)
Reagarding zmienna zadeklarowana w linii main.c 3 to jest znany, że trzyma wartość typu int widzianą przez odniesienie do typu do węzła @ 3.
Na pewno będziesz w stanie sam polować na podwójne wpisy i te dla d_var w swoim własnym eksperymencie, jeśli nie ufasz mi, że one również tam będą.
Przyjrzeniu generowanego asemblerze (stosując GCC przechodzą przełącznik -S
) wymienionego można spojrzeć na drodze kompilator używane te informacje w generacji kodu:
.file "main.c"
.comm i_var,4,4
.comm d_var,8,8
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
movl $-23, i_var
fldl .LC0
fstpl d_var
movl $0, %eax
popl %ebp
ret
.size main, .-main
.section .rodata
.align 8
.LC0:
.long -1717986918
.long 1069128089
.ident "GCC: (Debian 4.4.5-8) 4.4.5"
.section .note.GNU-stack,"",@progbits
przyjrzeniu instrukcje przypisania zobaczysz, że kompilator wymyślił odpowiednie instrukcje "mov", aby przypisać naszą wartość int i "fstp", aby przypisać naszą "podwójną" wartość.
Niemniej jednak oprócz instrukcji wybranych na poziomie maszyny nie ma informacji o typie tych wartości. Patrząc na wartość przechowywaną w .LC0, typ "double" o wartości 0,1 był nawet dzielony w dwóch kolejnych lokalizacjach magazynowych, każdy przez długi czas, aby spełnić znane "typy" asemblera.
W rzeczywistości przełamanie wartości w ten sposób było tylko jednym z innych możliwości, używając 8 kolejnych wartości "typu" .byte zrobiłoby równie dobrze.
zobacz: http://en.wikipedia.org/wiki/Symbol_table –
Każda zmienna w C musi mieć typ jako część deklaracji zmiennej (być może definicja, nigdy nie ma pewności, która). Kompilator odczytuje typ i zapamiętuje go. Nie ma tajemnicy co do rodzaju zmiennej. – DwB
Kompilator użyje prawidłowej instrukcji (ponieważ można podpisać niepodpisane i podpisane zgodnie z zasadami określonymi w normie). Istnieją różne instrukcje dotyczące podpisywania i niepodpisanych obliczeń, przynajmniej dla architektur, które widziałem. W przypadku języka C żadne dodatkowe informacje o typie nie są przechowywane w czasie wykonywania. – nhahtdh