1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#ifndef __CONSTANTS_H__
#define __CONSTANTS_H__

void print_constants();


//enum { constant_int = 65 };

//──────────────────────────────────────────────────
// GOOD
#ifndef BAD // gcc …
static const int   constant_int    = 65;
static const char* constant_string = "sixty-five";
static const float constant_float  = 65.05;

//──────────────────────────────────────────────────
// BAD strategy #1:  Use #define
//
// Problem:  Type might not be what you expect.

#elif BAD==2 // gcc -DBAD=2

#define constant_int    65
#define constant_string "sixty-five"
#define constant_float  65.05

//│ $ gcc -DBAD=2 constants_1.c constants_2.c
//│ /tmp/ccEXHgr8.o:(.rodata+0x0): multiple definition of `constant_int'
//│ /tmp/cclf5nhb.o:(.rodata+0x0): first defined here
//│ /tmp/ccOHc2wE.o:(.data+0x0): multiple definition of `constant_string'
//│ /tmp/ccpaprle.o:(.data+0x0): first defined here
//│ /tmp/ccOHc2wE.o:(.rodata+0xc): multiple definition of `constant_float'
//│ /tmp/ccpaprle.o:(.rodata+0xc): first defined here
//│ collect2: error: ld returned 1 exit status


//──────────────────────────────────────────────────
// BAD strategy #1:  const «type»
//
// Problem:  If you #include it from multiple files, you get linker errors.

#elif BAD==2 // gcc -DBAD=1 …

const int   constant_int    = 65;
const char* constant_string = "sixty-five";
const float constant_float  = 65.05;

//│ $ gcc -DBAD=1 constants_1.c constants_2.c
//│ /tmp/ccEXHgr8.o:(.rodata+0x0): multiple definition of `constant_int'
//│ /tmp/cclf5nhb.o:(.rodata+0x0): first defined here
//│ /tmp/ccOHc2wE.o:(.data+0x0): multiple definition of `constant_string'
//│ /tmp/ccpaprle.o:(.data+0x0): first defined here
//│ /tmp/ccOHc2wE.o:(.rodata+0xc): multiple definition of `constant_float'
//│ /tmp/ccpaprle.o:(.rodata+0xc): first defined here
//│ collect2: error: ld returned 1 exit status


//──────────────────────────────────────────────────
// BAD strategy #3:  static const «type»
//
// Problem:  If you don't use every constant in every file where it is #include'd,
// then you get an error.
#elif BAD==3 // gcc -DBAD=3 …

static const int   constant_int    = 65;
static const char* constant_string = "sixty-five";
static const float constant_float  = 65.05;
static const char* constant_unused = "UNUSED";

//│ $ gcc -DBAD=1 constants_1.c constants_2.c
//│ /tmp/ccEXHgr8.o:(.rodata+0x0): multiple definition of `constant_int'
//│ /tmp/cclf5nhb.o:(.rodata+0x0): first defined here
//│ /tmp/ccOHc2wE.o:(.data+0x0): multiple definition of `constant_string'
//│ /tmp/ccpaprle.o:(.data+0x0): first defined here
//│ /tmp/ccOHc2wE.o:(.rodata+0xc): multiple definition of `constant_float'
//│ /tmp/ccpaprle.o:(.rodata+0xc): first defined here
//│ collect2: error: ld returned 1 exit status

#endif


#endif /* end of include guard: __CONSTANTS_H__ */

© Copyright 2020 Alexander J. Quinn         This content is protected and may not be shared, uploaded, or distributed.