详细了解 static 和 extern 关键字的用法

C语言 static 和 extern关键字


static

一、 static函数 和 普通函数 区别

总的来说,static函数和普通函数的区别就是体现在作用域上面。static函数只是在本文件起作用。不可以被其他文件调用。先举个例子

例一

math.c

static int add(int a,int b)

{

return a+b;

}

main.c

#include <stdio.h>

int main() {

int a = 10,b=22;

printf("%d!\n",add(a,b));

return 0;

}

对上面文件用gcc进行编译

$ gcc main.c math.c

结果如下

main.c:15:20: warning: implicit declaration of function 'add' is invalid in C99

[-Wimplicit-function-declaration]

printf("%d!\n",add(a,b));

^

1 warning generated.

Undefined symbols for architecture x86_64:

"_add", referenced from:

_main in main-eaa78d.o

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

很明显的错误就是main.c文件中的函数 add 未定义。

我们做一下修改,加一个.h头文件

math.h

static int add(int a,int b);

main.c中引入

#include <stdio.h>

#include "math.h"

int main() {

int a = 10,b=22;

printf("%d!\n",add(a,b));

return 0;

}

再次使用gcc进行编译

$ gcc main.c math.c

结果是一样的

./math.h:8:12: warning: function 'add' has internal linkage but is not defined

[-Wundefined-internal]

static int add(int a,int b);

^

main.c:15:20: note: used here

printf("%d!\n",add(a,b));

^

1 warning generated.

Undefined symbols for architecture x86_64:

"_add", referenced from:

_main in main-c5f44a.o

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

这说的是add函数已经声明了,但是在main.c中并没有定义(虽然在 math.c中有定义,但是函数是static类型的,只在math.c文件中可见)。
有两种方式修改
一)将math.c中的函数改成普通函数

int add(int a,int b)

{

return a+b+10;

}

gcc编译会产生警告

main.c:15:20: warning: implicit declaration of function 'add' is invalid in C99

[-Wimplicit-function-declaration]

printf("%d!\n",add(a,b));

^

1 warning generated.

但是程序是可以正常执行的。要去除警告可以在math.h中声明普通函数,然后在main.c中引入math.h

int add(int a,int b);

二)在main.c中定义add()函数

#include <stdio.h>

static int add(int a,int b)

{

return a+b;

}

int main() {

int a = 10,b=22;

printf("%d!\n",add(a,b));

return 0;

}

千万注意的是,不可以同时在两个文件中定义普通的add函数。例如

例二

math.c

int add(int a,int b)

{

return a+b+10;

}

main.c

#include <stdio.h>

int add(int a,int b)

{

return a+b;

}

int main() {

int a = 10,b=22;

printf("%d!\n",add(a,b));

return 0;

}

这样是会报错的,函数被重复定义。所以说,从另一方面,static允许在不同文件中定义同名函数,这也是static函数除作用域之外的另一用途。

二、static变量 和 普通变量区别

static变量和static函数异曲同工,也是对作用域的限定。


extern

一、变量前加extern关键字

对于函数有声明定义两步。同样对于变量严格来说也是分声明定义。定义一个变量就要为其分配内存并赋值。如果没指定值则根据变量类型赋相应的默认值。

int var1;  // 相当于是  声明和定义合成为一步

extern int var2; // 仅仅是声明

也就是说在变量前面如果加上了extern关键字,对于这个变量来说只是进行了声明并没有定义。下面举几个例子进行对extern的用法进行说明

例一

main.c

#include <stdio.h>

int var1;

extern int var2;

int main()

{

var1 = 11;

var2 = 12;

printf("var1=%d; var2=%d\n",var1,var2);

return 0;

}

gcc进行编译

$ gcc main.c

Undefined symbols for architecture x86_64:

"_var2", referenced from:

_main in main-179d3c.o

ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

链接的时候没有找到变量var2。因为var2只是进行了声明,并没有定义,所以编译能通过,到了链接的时候就找不到了。

例二

main.c

#include <stdio.h>

int var1 = 11;

extern int var2 = 12;

int main() {

printf("var1=%d; var2=%d\n",var1,var2);

return 0;

}

gcc进行编译

$ gcc main.c

main.c:5:12: warning: 'extern' variable has an initializer [-Wextern-initializer]

extern int var2 = 12;

^

1 warning generated.

只是一个警告,程序是可以正确执行的。也就是说 extern int var2 = 12 这种方式也是对变量进行了定义,但这是不合规则的,所以给你个警告。

extern 主要是对外部变量进行引用。所以正确合规的用法举例如下

例三

math.c

int var = 12;

main.c

#include <stdio.h>

extern int var;

int main()

{

printf("var = %d\n",var);

return 0;

}

gcc进行编译

$ gcc main.c math.c

没有问题。 因为 var 变量是进行了定义的。 所以在main.c中是可以找到var变量的。

例四

math.c

extern int var = 12;

main.c

#include <stdio.h>

extern int var;

int main()

{

printf("var = %d\n",var);

return 0;

}

gcc 进行编译

$ gcc main.c math.c

static/math.c:61:12: warning: 'extern' variable has an initializer [-Wextern-initializer]

extern int var = 12;

^

1 warning generated.

也是可以通过的,只是多了一个警告。参照 例二

总的来说,只要是一个全局变量进行了定义。在其他文件中通过extern关键字就可以进行引用。

二、extern 函数

函数默认都是extern类型的。也就是说函数前面没有static关键字修饰,那就都是extern

int add(int a, int b);

// 等价于

extern int add(int a, int b);

上面关于 extern 修饰的变量,必须要是定义的全局变量,在其他文件中才能通过 extern 进行引用。 函数内定义的变量是没法被其他文件进行引用的。

本文转载自:迹忆客(https://www.jiyik.com)

以上是 详细了解 static 和 extern 关键字的用法 的全部内容, 来源链接: utcz.com/z/290174.html

回到顶部