c言語において
#ifndef HEADER_H
#define HEADER_H
const double PI = 3.14;
#endif
#include "header.h"
#include "header.h"
int main(void) {}
のようなコードをコンパイルすることはできません。
$ gcc main.c a.c
/usr/bin/ld: /tmp/cc4BWsZc.o:(.rodata+0x0): multiple definition of `PI'; /tmp/ccXsx13d.o:(.rodata+0x0): first defined here
collect2: error: ld returned 1 exit status
C++17以降では同一のコードをコンパイルすることができます。
nm
コマンドでシンボル情報を見てみます。
$ g++ main.cpp a.cpp
$ nm --demangle a.out
0000000000003e00 d _DYNAMIC
0000000000003fc0 d _GLOBAL_OFFSET_TABLE_
0000000000002000 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000002008 r PI // シンボルタイプが小文字であればローカルシンボル
0000000000002010 r PI
略
0000000000001129 T main
00000000000010a0 t register_tm_clones
PI
がローカルシンボルであることが分かります。
C言語においてstatic const double PI = 3.14;
と同じことになります。
結論
C言語で定数がほしかったら#define
じゃなくってstatic const
でいいってこと?
constexpr
でよくね?
$ gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ --version
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
https://timsong-cpp.github.io/cppwp/n4659/diff.basic
https://timsong-cpp.github.io/cppwp/n4659/basic.link#3
余談
https://timsong-cpp.github.io/cppwp/n4659/basic.def#2.18
に
int a; // defines a
とあるので
int a;
int a;
int main() {}
というコードはC言語でコンパイルできますがC++ではコンパイルできません。
https://docs.microsoft.com/ja-jp/cpp/cpp/declarations-and-definitions-cpp?view=msvc-160#definitions
ここには宣言とあるのでmsvcではコンパイルできるのかと思いましたが
ではコンパイルできませんでした。