- 内部結合 : Internal Linkage
- 外部結合 : External Linkage
ファイルスコープのオブジェクト定義(いわゆるグローバル変数定義)
static | 記憶クラス指定子なし | extern | |
C言語 | 内部結合定義 | 外部結合定義 | 仕様なし |
C++ | 内部結合定義 | 非const: 外部結合定義 const: 内部結合定義 |
外部結合定義 |
static | 記憶クラス指定子なし | extern | |
C言語 | 内部結合定義 | 外部結合定義 | 仕様なし |
C++ | 内部結合定義 | 非const: 外部結合定義 const: 内部結合定義 |
外部結合定義 |
プリプロセッサへの命令
#include
#define
#if
#ifdef
#error
#warning
#pragma
定義と初期化
1 2 3 4 5 |
int x = 0; int main(void) { /* 中略 */ } |
翻訳単位外(ファイルの外)で定義したグローバル変数を参照する。メモリは割り当てない。
1 2 3 4 5 |
extern int x; int main(void) { /* 中略 */ } |
どこかに外部定義があれば外部宣言としてふるまい、なければ外部定義としてふるまう。
したがって同じ名前の仮定義が複数存在しても、ひとつのメモリ領域を参照する。
1 2 3 4 5 |
int x; int main(void) { /* 中略 */ } |
上記のソースコードだけでは『定義』であるか『宣言』であるか確定できない。
下記のようにswitchブロックの内部で変数宣言をおこなうとコンパイルエラーとなる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <stdio.h> int main(void) { int i; for (i = 0 ; i < 100 ; i++) { switch (i%2) { case 0: char msg_even[] = "EVEN"; printf("%3d is %s\n", i, msg_even); break; case 1: char msg_odd[] = "ODD"; printf("%3d is %s\n", i, msg_odd); break; default: printf("%3d is UNKNOWN\n", i); break; } } return 0; } |
下記のようにコンパイラの最適化で省略される個所にブレイクポイントを設定できないことがあります。
1 2 3 4 5 6 7 8 |
while (num_of_line > 0) { /* 中略 */ if (num_of_lines < 10) { continue; /* ここにブレイクポイントを設定できない */ } } |
自己参照する要素を持つ構造体を定義するとコンパイルエラーとなる
1 2 3 4 |
typedef struct st_node { int id; NODE *node; } NODE; |
1 2 |
sample.c:6:3: error: unknown type name ‘NODE’ NODE *node;<code> |
危険なキャストをおこなってバグを誘発した例をみつけたのでご紹介します。
不具合の経緯としては
log10() を呼び出すプログラムをコンパイルすると以下のようなエラーが発生する。
1 2 3 4 5 |
$ gcc main.c /tmp/ccuhFgLT.o: In function `main': main.c:(.text+0x4d): undefined reference to `log10' main.c:(.text+0x75): undefined reference to `log10' collect2: error: ld returned 1 exit status |
C/C++混在環境において 「no definition for “xxx”」などの関数定義が存在しないエラーが発生してリンクに失敗する。
『 マングル (mangle) 』, 『 名前マングリング (name mangling) 』
続きを読む