2019年4月5日 星期五

c vs c++ - const 修飾詞

c 和 c++ 對 const 有不同的解釋

a.c
1 #include <stdio.h>
2
3 extern const int abc;
4
5 int main(int argc, char *argv[])
6 {
7   printf("hello c++, abc: %d\n", abc);
8   return 0;
9 }

b.c
1 const int abc=1;
2
3 int fun1()
4 {
5   return abc + 5;
6 }

gcc -save-temps a.c b.c -o a

list 1 b.o.elf
 1 ELF Header:
 2   Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
 3   Class:                             ELF64
 4   Data:                              2's complement, little endian
 5   Version:                           1 (current)
 6   OS/ABI:                            UNIX - System V
 7   ABI Version:                       0
 8   Type:                              REL (Relocatable file)
 9   Machine:                           Advanced Micro Devices X86-64
10   Version:                           0x1
11   Entry point address:               0x0
12   Start of program headers:          0 (bytes into file)
13   Start of section headers:          576 (bytes into file)
14   Flags:                             0x0
15   Size of this header:               64 (bytes)
16   Size of program headers:           0 (bytes)
17   Number of program headers:         0
18   Size of section headers:           64 (bytes)
19   Number of section headers:         12
20   Section header string table index: 11
21 
22 Section Headers:
23   [Nr] Name              Type             Address           Offset
24        Size              EntSize          Flags  Link  Info  Align
25   [ 0]                   NULL             0000000000000000  00000000
26        0000000000000000  0000000000000000           0     0     0
27   [ 1] .text             PROGBITS         0000000000000000  00000040
28        000000000000000e  0000000000000000  AX       0     0     1
29   [ 2] .data             PROGBITS         0000000000000000  0000004e
30        0000000000000000  0000000000000000  WA       0     0     1
31   [ 3] .bss              NOBITS           0000000000000000  0000004e
32        0000000000000000  0000000000000000  WA       0     0     1
33   [ 4] .rodata           PROGBITS         0000000000000000  00000050
34        0000000000000004  0000000000000000   A       0     0     4
35   [ 5] .comment          PROGBITS         0000000000000000  00000054
36        000000000000001d  0000000000000001  MS       0     0     1
37   [ 6] .note.GNU-stack   PROGBITS         0000000000000000  00000071
38        0000000000000000  0000000000000000           0     0     1
39   [ 7] .eh_frame         PROGBITS         0000000000000000  00000078
40        0000000000000038  0000000000000000   A       0     0     8
41   [ 8] .rela.eh_frame    RELA             0000000000000000  000001c8
42        0000000000000018  0000000000000018   I       9     7     8
43   [ 9] .symtab           SYMTAB           0000000000000000  000000b0
44        0000000000000108  0000000000000018          10     9     8
45   [10] .strtab           STRTAB           0000000000000000  000001b8
46        000000000000000e  0000000000000000           0     0     1
47   [11] .shstrtab         STRTAB           0000000000000000  000001e0
48        000000000000005c  0000000000000000           0     0     1
49 Key to Flags:
50   W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
51   L (link order), O (extra OS processing required), G (group), T (TLS),
52   C (compressed), x (unknown), o (OS specific), E (exclude),
53   l (large), p (processor specific)
54 
55 There are no section groups in this file.
56 
57 There are no program headers in this file.
58 
59 There is no dynamic section in this file.
60 
61 Relocation section '.rela.eh_frame' at offset 0x1c8 contains 1 entry:
62   Offset          Info           Type           Sym. Value    Sym. Name + Addend
63 000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0
64 
65 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
66 
67 Symbol table '.symtab' contains 11 entries:
68    Num:    Value          Size Type    Bind   Vis      Ndx Name
69      0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
70      1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS b.c
71      2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
72      3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
73      4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
74      5: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
75      6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
76      7: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
77      8: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
78      9: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 abc
79     10: 0000000000000000    14 FUNC    GLOBAL DEFAULT    1 fun1
80 
81 No version information found in this file.

這個問題要從 link time 才能發現, 並不是編譯時期的問題, list 1 L78 顯示 bind 欄位是 global, 所以其他編譯單元看得到這個 const abc 變數。

a.cpp
1 #include <stdio.h>
2
3 extern const int abc;
4
5 int main(int argc, char *argv[])
6 {
7   printf("hello c++, abc: %d\n", abc);
8   return 0;
9 }

b.cpp
1 const int abc=1;
2
3 int fun1()
4 {
5   return abc + 5;
6 }

descent@debian64:tmp$ g++ -save-temps a.cpp b.cpp -o a
/usr/bin/ld: a.o: in function `main':
a.cpp:(.text+0x11): undefined reference to `abc'
collect2: error: ld returned 1 exit status

list 2 b.cpp.o.elf
 1 ELF Header:
 2   Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
 3   Class:                             ELF64
 4   Data:                              2's complement, little endian
 5   Version:                           1 (current)
 6   OS/ABI:                            UNIX - System V
 7   ABI Version:                       0
 8   Type:                              REL (Relocatable file)
 9   Machine:                           Advanced Micro Devices X86-64
10   Version:                           0x1
11   Entry point address:               0x0
12   Start of program headers:          0 (bytes into file)
13   Start of section headers:          576 (bytes into file)
14   Flags:                             0x0
15   Size of this header:               64 (bytes)
16   Size of program headers:           0 (bytes)
17   Number of program headers:         0
18   Size of section headers:           64 (bytes)
19   Number of section headers:         12
20   Section header string table index: 11
21 
22 Section Headers:
23   [Nr] Name              Type             Address           Offset
24        Size              EntSize          Flags  Link  Info  Align
25   [ 0]                   NULL             0000000000000000  00000000
26        0000000000000000  0000000000000000           0     0     0
27   [ 1] .text             PROGBITS         0000000000000000  00000040
28        000000000000000b  0000000000000000  AX       0     0     1
29   [ 2] .data             PROGBITS         0000000000000000  0000004b
30        0000000000000000  0000000000000000  WA       0     0     1
31   [ 3] .bss              NOBITS           0000000000000000  0000004b
32        0000000000000000  0000000000000000  WA       0     0     1
33   [ 4] .rodata           PROGBITS         0000000000000000  0000004c
34        0000000000000004  0000000000000000   A       0     0     4
35   [ 5] .comment          PROGBITS         0000000000000000  00000050
36        000000000000001d  0000000000000001  MS       0     0     1
37   [ 6] .note.GNU-stack   PROGBITS         0000000000000000  0000006d
38        0000000000000000  0000000000000000           0     0     1
39   [ 7] .eh_frame         PROGBITS         0000000000000000  00000070
40        0000000000000038  0000000000000000   A       0     0     8
41   [ 8] .rela.eh_frame    RELA             0000000000000000  000001c8
42        0000000000000018  0000000000000018   I       9     7     8
43   [ 9] .symtab           SYMTAB           0000000000000000  000000a8
44        0000000000000108  0000000000000018          10    10     8
45   [10] .strtab           STRTAB           0000000000000000  000001b0
46        0000000000000018  0000000000000000           0     0     1
47   [11] .shstrtab         STRTAB           0000000000000000  000001e0
48        000000000000005c  0000000000000000           0     0     1
49 Key to Flags:
50   W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
51   L (link order), O (extra OS processing required), G (group), T (TLS),
52   C (compressed), x (unknown), o (OS specific), E (exclude),
53   l (large), p (processor specific)
54 
55 There are no section groups in this file.
56 
57 There are no program headers in this file.
58 
59 There is no dynamic section in this file.
60 
61 Relocation section '.rela.eh_frame' at offset 0x1c8 contains 1 entry:
62   Offset          Info           Type           Sym. Value    Sym. Name + Addend
63 000000000020  000200000002 R_X86_64_PC32     0000000000000000 .text + 0
64 
65 The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
66 
67 Symbol table '.symtab' contains 11 entries:
68    Num:    Value          Size Type    Bind   Vis      Ndx Name
69      0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
70      1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS b.cpp
71      2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
72      3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
73      4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
74      5: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
75      6: 0000000000000000     4 OBJECT  LOCAL  DEFAULT    4 _ZL3abc
76      7: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
77      8: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
78      9: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
79     10: 0000000000000000    11 FUNC    GLOBAL DEFAULT    1 _Z4fun1v
80 
81 No version information found in this file.

list 2 L75 bind 顯示是 local, 所以其他編譯單元看不到。

c++ 的 const 會有類似 static 的效果, 這個 abc 變數只能在 b.cpp 檔案使用, a.cpp 看不到這個變數。

不過我在 c++ primer 3rd 找不到這個說明, 不知道哪本書有寫?

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。