关于C语言中static 、extern关键字的用法

C语言 码拜 9年前 (2016-01-30) 1559次浏览
由于刚开始接触C不久,学到这点的时候,感觉书中这两个关键字的用法很乱,有点迷惑,希望好心人指点
解决方案:3分
解决方案:2分
假如您想在其他文件中使用这个函数,要么您就在 c 文件中将这个函数定义为 extern 类型,或在头文件中将这个函数定义为 static inline 类型,这样能确保函数能在其他 c 文件中使用.
在其他 c 文件中使用的时候使用 extern 将其导入.
解决方案:2分
学习,基础啊,很重要哇
解决方案:4分
static关键字
static关键字一共有3个不同的用途:
1.假如用于函数内部的局部变量声明时,static关键字的作用是改变局部变量的存储类型,从自动变量改为静态变量,也就是说这个局部变量不在存储在堆栈或寄存器中,而是在编译的时候由编译器分配一个静态的地址空间,但这个变量的作用域不受影响,依然仅局限在声明它的函数内部才可以访问。需要说明的是一旦函数内部的局部变量被声明为static,这个函数就有可能变得不可重入(可重入是指相同的参数输入会有相同的结果输出)
2.假如static关键字用于函数定义时,这个函数就只能在定义该函数的C文件中引用,该C文件外的代码将无法调用这个函数。
3.在用于全局变量的声明时,static关键字的作用相似于函数的情况,这个全局变量的作用域将局限在声明该变量的C文件内部,这个C文件之外的代码将无法访问这个变量(事实上,假如采用指针的方式进行访问时可以的,但是这样就违背了将一个全局变量声明为static的初衷了)
对于函数名和全局变量的static声明相似于C++中的private关键字,利用static关键字可以再C程序中实现相似于C++中封装的概念,将局部的、私有的函数或变量声明为static,可以屏蔽C文件中的实现细节,降低一个项目中若干C文件之间的耦合度,为软件的模块化开发、测试、维护、移植提供便利条件。
extern关键字
默认情况下,C语言中的全局变量和函数的作用域仅限于定义或什么这个函数或变量的C文件内部,假如需要从这个C文件之外访问这些函数或全局变量就需要使用extern关键字。这是原因是C编译器是以C文件为单位进行编译的,假如这个C文件中引用了其他文件中定义的函数或变量,编译器将无法找到这个函数或变量的定义,从而给出该函数或变量未定义的错位信息。
使用extern的方式有2种:
1.在C文件中直接声明某个其他文件中定义的函数或全局变量为extern,从而告诉编译器这个函数或变量是在其他C文件中定义的。
2.在头文件中声明某个函数或变量为extern,然后在需要引用该函数或变量的C文件中包含这个头文件
解决方案:4分
extern 是外链?你们说说下面的D是外链还是内链?

static int x = 0;
void f (void)
{
    extern int x;     //D
}
解决方案:3分
©ISO/IEC ISO/IEC 9899:1999 (E)
6.2.2 Linkages of identifiers
4 For an identifier declared with the storage-class specifier extern in a scope in which a
prior declaration of that identifier is visible,23) if the prior declaration specifies internal or
external linkage, the linkage of the identifier at the later declaration is the same as the
linkage specified at the prior declaration. If no prior declaration is visible, or if the prior
declaration specifies no linkage, then the identifier has external linkage.
解决方案:3分
所以说嘛。楼上种种回答太不负责任了。
解决方案:2分
鉴于12#说的不负责任,本人要说一下本人的观点:
内联和外联是相对于作用域而言的,而不是说文件
用你的例子说:
static int x = 0;//作用域是文件(或说全局),不可被外部文件调用,只能够被该文件内函数调用。这是内联

void f (void)
{
extern int x;     //作用域是本函数,此处x表示其调用的是函数作用域以外的x即全局x,这才叫他外联
}

解决方案:3分
作用域和链接是两回事,不要混为一谈。标识符的链接和标识符的作用域没有什么必然的关系。下面的例子是合法的,没有什么你所谓的外部和内部:

static int x = 0;
void f (void) {/* …… */}
extern int x;
解决方案:3分
@均陵鼠侠
这个例子举的,本人竟无言以对。
好吧,那看来只有本人是这样理解的。
解决方案:3分
1.关键字static的作用是什么?
这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:
1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。

#include <stdio.h>
int fun(void);
int main(void)
{
      printf("fun() = %d\n", fun());
      printf("fun() = %d\n", fun());
      printf("fun() = %d\n", fun());
      return 0;
}
int fun(void)
{
      static int m = 10;    //static变量只会初始化一次,第二次调用这个函数的时候不会将 m 的值赋为10 
      m += 1;
      return m;
}
运行结果:
fun() = 11
fun() = 12
fun() = 13
#include <stdio.h>
int fun(void);
int main(void)
{
      printf("fun() = %d\n", fun());
      printf("fun() = %d\n", fun());
      printf("fun() = %d\n", fun());
      return 0;
}
int fun(void)
{
      static int m;
      m = 10;    // 这条语句每次调用这个函数时都会被执行,将 m 的值赋为10
      m += 1;
      return m;
}
运行结果:
fun() = 11
fun() = 11
fun() = 11

2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。

3.c文件
static int tmp = 22;
test.c文件
#include <stdio.h>
extern static int tmp;    //对于变量来说,这句必不可少
int main(void)
{
      printf("%d\n", tmp);
      return 0;
}
运行结果:
gcc test.c 3.c 
test.c:4: error: multiple storage classes in declaration specifiers
运行结果:
gcc test.c 3.c 
test.c:4: error: multiple storage classes in declaration specifiers

3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

3.c文件
static int fun(void)
{
      return 1;
}
test.c文件
#include <stdio.h>
extern int fun(void);    //对于函数来说这句要不要不影响
int main(void)
{
      printf("%d\n", fun());
      return 0;
}
运行结果:
$ gcc test.c 3.c    
/tmp/ccQMDvZt.o: In function `main"":
test.c:(.text+0x5): undefined reference to `fun""
collect2: ld returned 1 exit status
解决方案:4分
上面代码有点问题,更改了下,本人删除不了。
1.关键字static的作用是什么?
这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:
1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
注:定义变量时加不加static关键字,关系到变量的存储类型,代码块内不加static关键字的变量存放在栈中,加了static关键字则存放在.data/.bss段中,而具体是存放在.data段还是.bss段则要看定义变量时有没有初始化。

#include <stdio.h>
int fun(void);
int main(void)
{
      printf("fun() = %d\n", fun());
      printf("fun() = %d\n", fun());
      printf("fun() = %d\n", fun());
      return 0;
}
int fun(void)
{
      static int m = 10;    //static变量只会初始化一次,第二次调用这个函数的时候不会将 m 的值赋为10 
      m += 1;
      return m;
}
运行结果:
fun() = 11
fun() = 12
fun() = 13
#include <stdio.h>
int fun(void);
int main(void)
{
      printf("fun() = %d\n", fun());
      printf("fun() = %d\n", fun());
      printf("fun() = %d\n", fun());
      return 0;
}
int fun(void)
{
      static int m;
      m = 10;    // 这条语句每次调用这个函数时都会被执行,将 m 的值赋为10
      m += 1;
      return m;
}
运行结果:
fun() = 11
fun() = 11
fun() = 11

2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。

3.c文件
static int tmp = 22;
test.c文件
#include <stdio.h>
extern static int tmp;  
int main(void)
{
      printf("%d\n", tmp);
      return 0;
}
运行结果:
gcc test.c 3.c 
test.c:4: error: multiple storage classes in declaration specifiers

3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

3.c文件
static int fun(void)
{
      return 1;
}
test.c文件
#include <stdio.h>
extern static int fun(void);   
int main(void)
{
      printf("%d\n", fun());
      return 0;
}
运行结果:
gcc test.c 3.c 
test.c:4: error: multiple storage classes in declaration specifiers

/*************************吐槽,是本人眼睛有问题吗,这个校验码输了半天也输不对,赶上12305了*****************************/


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明关于C语言中static 、extern关键字的用法
喜欢 (0)
[1034331897@qq.com]
分享 (0)