Skip to content

Instantly share code, notes, and snippets.

@sawaken
Last active August 29, 2015 14:23
Show Gist options
  • Save sawaken/44288764ff4a447da109 to your computer and use it in GitHub Desktop.
Save sawaken/44288764ff4a447da109 to your computer and use it in GitHub Desktop.
C's extern

#extern修飾子の意味

外部で定義される変数であることを宣言するための修飾子

ただし

extern修飾子を付けて変数aを宣言する => 変数aは外部定義される

は成り立つが、その逆

変数aは外部定義される => 変数aは、extern修飾子を付けて宣言されている

は成り立たない。

外部定義を行うが、extern修飾子は使わない場合

/* a.c */
#include <stdio.h>
int a;
int main()
{
  printf("%d\n", a);
}
/* b.c */
int a = 1;
$ gcc -c a.c b.c
$ gcc a.o         # このコンパイル(リンク)は通ってほしくない。
$ ./a.out
> 0
$ gcc a.o b.o     # こっちが本来の想定
$ ./a.out
> 1

そこでextern修飾子を使うと、1つ目のようなコンパイルを通せなくすることができる。

/* a2.c */
#include <stdio.h>
extern int a;
int main()
{
  printf("%d\n", a);
}
$ gcc -c a.c b.c
$ gcc a.o
a2.o: In function `main':
a2.c:(.text+0x6): undefined reference to 'a'
collect2: error: ld returned 1 exit status
$ gcc a.o b.o
$ ./a.out
> 1

関数の場合はブロック定義の有る/無しで実体/非実体が定まるので、extern修飾子を付けても付けなくても変わらない。

/* main.c */
#include <stdio.h>
int add(int, int);
int main()
{
  printf("%d\n", add(1, 2));
}
/* add.c */
int add(int a, int b)
{
  return a + b;
}
$ gcc -c main.c add.c
$ gcc main.o
main.o: In function `main':
main.c:(.text+0x2d): undefined reference to 'add'
$ gcc main.o add.o
$ ./a.out
> 3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment