Linux C —— 三种链接属性(external、internal、none)

一、问题引出

当多个源文件链接在一起,我们如何处理相同名字的标识符?假设多个源文件均含有变量a,那么它的值到底采用哪个源文件定义的值呢?这就涉及到标识符的链接属性。

二、对象

链接属性针对标识符而言,对象通常是变量、函数名、形参。

三、分类

链接属性(linkage)分为三种——外部(external)、内部(internal)、无(none)

3.1 外部(external)

 判别依据

//demo0.c
#include <stdio.h>
int x;
int func(int a){
    int y;
}
  • 在demo0.c中,x、func具有external的链接属性,简而言之,并非声明于代码块内的变量,缺省情况下具有external链接属性,(函数名也不包含于任何代码块)。
//demo1.c
int x = 10;                                       #include <stdio.h>
void print(void)                                  int main(void)
{                                                 {
    printf("Hello World!\n");                         extern int x;
}                                                     printf("%d ");
                                                      print();
                                                      return 0;
                                                  }       //demo2.c
  • 在文件A中具有external链接属性的变量(或函数名)具有全局可见性,对于变量,在声明前加extern表示引用文件A中的对应变量,函数则可以直接使用。
  • 当用于具有文件作用域的声明时,这个关键字是可选的。然而,如果你在一个地方定义变量,并在使用这个变量的其他源文件的声明中添加external关键字,可以使读者更容易理解你的意图
  • 例如demo1.c中x和print具有external链接属性,在demo2.c中,extern int x表示这里的x就是demo1.c中的x,这里的x链接属性就是external,print就是demo1.c中的print 。

3.2 内部(internal)

判断依据
 

//demo3.c
#include <stdio.h>
static int x;
static int func(int a){
    int y;
}
  • 缺省情况下,除了上述说明的external属性以外,其余均为none。因此internal属性出现在static修饰之后。
  • demo3.c中,如果删除static,则和demo0.c相同,即x和func在原先属于external,在用static关键字修饰之后则有了internal属性,即只能够在demo3.c一个文件中访问,其他文件不能访问。
     
//demo4.c
static int x = 10;                                #include <stdio.h>
static void print(void)                           int main(void)
{                                                 {
    printf("Hello World!\n");                         extern int x;
}                                                     printf("%d ");
                                                      print();
                                                      return 0;
                                                  }       //demo5.c
  • 上述两个程序不能成功链接。当具有external属性的变量(或函数名)用static关键字修饰之后,就具有了internal链接属性,其他文件不能访问它们。因此,demo5.c中extern int x; 和 print(); 是错误的,因为x和print不再是external的链接属性了。
  • 不要用static关键字修饰none属性的标识符,对于链接属性,static只能修改external属性的标识符,若修饰none属性的,改变的是存储类型而非链接属性

3.3 无(none)

判断依据

//demo6.c
#include <stdio.h>
int x;
int func(int a){
    int y;
}
  • 在demo6.c中,a和y具有none的链接属性,简而言之, 函数形式参数和代码块内声明的变量在缺省情况下具有none链接属性 。
  • none链接属性标识符仅允许作用域内访问。

当用于不同的上下文环境时,static关键字具有不同的意思。确实很不幸,因为这总是给C程序员新手带来混淆。本节对static关键字作了总结,再加上后续的例子程序,应该能够帮助你搞清这个问题。

当它用于函数定义时,或用于代码块之外的变量声明时,static关键字用于修改标识符的链接属性,从external改为internal,但标识符的存储类型和作用域不受影响。用这种方式声明的函数或变量只能在声明它们的源文件中访问。

当它用于代码块内部的变量声明时,static关键字用于修改变量的存储类型,从自动变量修改为静态变量,但变量的链接属性和作用域不受影响。用这种方式声明的变量在程序执行之前创建,并在程序的整个执行期间一直存在,而不是每次在代码块开始执行时创建,在代码块执行完毕后销毁。

四、Tips

  • 链接属性的改变不会改变作用域(scope)。
  • 链接不是 #include,不能直接 #include”demox.c” 来链接不同的源文件,否则会得出不同结论,链接方式多样,我用的是gcc命令,gcc -o filename file1.c file2.c 。
  • 链接属性最好和作用域、存储类型一起学习(static关键字涉及了三者),这篇博文主要内容是链接属性。
  • 上述程序范例很相似,可以通过寻找不同处来理解链接属性。
  • 链接属性不仅意味着能不能访问变量,也意味着能不能在文件中定义同名变量或函数名。
  • 当extern关键字用于源文件中一个标识符的第1次声明时,它指定该标识符具有external链接属性。但是,如果它用于该标识符的第2次或以后的声明时,它并不会更改由第1次声明所指定的链接属性。
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值