打印
[C语言]

extern什么作用?

[复制链接]
3269|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
各位大神 我写了一个程序:
test.c 定义了一些声明的变量,函数,程序如下:
#include <stdio.h>
void sort(void)
{
        printf("**********************\n");
}
int a = 10;


main.c函数引用test.c文件里定义的函数或变量:
#include <stdio.h>
int a;
void sort(void);
int main(int argc, const char *argv[])
{
        printf("%d\n", a);
        sort();
        return 0;
}

打印结果:
lzhh@lzhh-virtual-machine:~/Cjob$ ./test
10
**********************

一半引用外部文件的函数或变量都会想到extern关键字,可是我实验的这个程序不用使用extern就能引用外部函数或变量,我现在有点迷惑了,好像extern关键字没啥用啦。
大神们我写的程序有问题吗?如果没问题那extern关键字还有啥用呢?

相关帖子

沙发
yiilanying| | 2018-8-29 12:03 | 只看该作者
extern 是外部变量的关键字,一般不这样用,在tes.c中
#include <stdio.h>
int  a;
void sort(void)
{
        printf("**********************\n");
        a=10;
}
在主函数中main.c函数引用test.c文件里定义的函数或变量:
#include <stdio.h>
int a;然后再改成extern int a;看看有什么不同,你就理解了extern的用法
void sort(void);
int main(int argc, const char *argv[])
{
        sort();
        printf("%d\n", a);
        return 0;
}

使用特权

评论回复
板凳
yiilanying| | 2018-8-29 12:03 | 只看该作者
extern 是外部变量的关键字,一般不这样用,在tes.c中
#include <stdio.h>
int  a;
void sort(void)
{
        printf("**********************\n");
        a=10;
}
在主函数中main.c函数引用test.c文件里定义的函数或变量:
#include <stdio.h>
int a;然后再改成extern int a;看看有什么不同,你就理解了extern的用法
void sort(void);
int main(int argc, const char *argv[])
{
        sort();
        printf("%d\n", a);
        return 0;
}

使用特权

评论回复
地板
yanghelovehuang|  楼主 | 2018-8-29 13:00 | 只看该作者
yiilanying 发表于 2018-8-29 12:03
extern 是外部变量的关键字,一般不这样用,在tes.c中
#include
int  a;

大神谢谢您的回复,我按照您的方法试了 感觉没什么变化,打印出来的a都等于10,看图片:

Ubuntu-2018-08-29-12-59-45.png (366.1 KB )

Ubuntu-2018-08-29-12-59-45.png

使用特权

评论回复
5
dun20062006| | 2018-8-29 14:32 | 只看该作者
extern 是声明 已经定义的全局变量,其它个.h ,.C文件中使用

使用特权

评论回复
6
Vansm| | 2018-8-29 17:54 | 只看该作者
extern 是告诉编译器,这个函数不是在这个文件中实现的,不用再这个文件中查找

使用特权

评论回复
7
wono01| | 2018-8-30 10:12 | 只看该作者
extern 是告诉编译器,这个变量我已经声明了,你在链接的时候查找,现在找不到这个变量不算错。
主要是现在的ide你不声明extern,有的时候他也不报错。
最简单的一点,你的sort函数或者变量a,你试试在4个文件里面引用看看,另外你那个int a应该是初值有问题,你试试换个位置定义a(main函数里面的那个),有可能打印结果就不一样了。

使用特权

评论回复
8
ddllxxrr| | 2018-8-31 18:43 | 只看该作者
声明是外部变量

使用特权

评论回复
9
linqing171| | 2018-9-3 21:45 | 只看该作者
外部的变量必须加extern。函数加不加都可以。
只要是声明了就行,无论在本c文件还是在外面的c文件均可以。

使用特权

评论回复
10
yanghelovehuang|  楼主 | 2018-9-4 09:45 | 只看该作者
linqing171 发表于 2018-9-3 21:45
外部的变量必须加extern。函数加不加都可以。
只要是声明了就行,无论在本c文件还是在外面的c文件均 ...

大神 我还是不太明白,我上面的程序test.c中的int a不就是外部变量吗? 可是没加extern 可是在main.c中 我还是可以用a啊

使用特权

评论回复
11
john_lee| | 2018-9-4 10:21 | 只看该作者

使用特权

评论回复
12
linqing171| | 2018-9-4 14:22 | 只看该作者
yanghelovehuang 发表于 2018-9-4 09:45
大神 我还是不太明白,我上面的程序test.c中的int a不就是外部变量吗? 可是没加extern 可是在main.c中  ...

你这是在两个文件里两个变量,重名,但是是不同的变量。
同理,你不同的函数里面也都可以有int a; 但是他的作用域(scope)是不一样的。

使用特权

评论回复
13
yanghelovehuang|  楼主 | 2018-9-4 15:21 | 只看该作者
linqing171 发表于 2018-9-4 14:22
你这是在两个文件里两个变量,重名,但是是不同的变量。
同理,你不同的函数里面也都可以有int a; 但是他 ...

我知道变量不能重命名, 可是编译时也没报错,而且既然作用域不同为什么在test.c里给a赋值,在main.c里能够打印出test里赋的值呢?求大神说下

使用特权

评论回复
14
linqing171| | 2018-9-4 16:38 | 只看该作者
首先是你只抓屏了extern int a;的这个
其次你重启一下电脑,先运行 int a 的这个程序,再运行extern int a的这个程序,再运行int a的这个程序。可以提前编译好。
最后,建议你测试完 extern int a这个后,上会网,听听歌,再来测试 int a 这个。


建议你修改如下:

test.c 修改:

int  a;
void sort(void)
{
        a=10;
        printf("test.c sort : a=%d\n",a);
}



======================
main.c 修改
===============

void sort(void);
int main(int argc, const char *argv[])
{
        a=3;
        sort();
        printf("main.c a=%d\n", a);
        return 0;
}

使用特权

评论回复
15
yanghelovehuang|  楼主 | 2018-9-5 09:30 | 只看该作者
linqing171 发表于 2018-9-4 16:38
首先是你只抓屏了extern int a;的这个
其次你重启一下电脑,先运行 int a 的这个程序,再运行extern int a ...

嗯嗯 谨遵大神意见 我马上试试。

使用特权

评论回复
16
john_lee| | 2018-9-5 10:11 | 只看该作者
我的这个回帖的第2点,正是你这个程序的情况,
当某一个目标文件存在已初始化的变量,而其它目标文件存在该变量同名的尝试性变量,则链接程序会使用已初始化的变量的大小为该变量分配存储,并将所有相同名称的尝试性变量都链接到这个存储地址。


你在 test.c 中定义了 int a = 10; 这是“已初始化变量”,然后在 main.c 又定义了 int a; 这是“尝试性变量”,链接程序会自动将两个文件的 a 变量合并。两个文件中对 a 变量的访问,实际上都是对合并后的 a 变量的访问。

使用特权

评论回复
17
linqing171| | 2018-9-5 22:30 | 只看该作者
yanghelovehuang 发表于 2018-9-5 09:30
嗯嗯 谨遵大神意见 我马上试试。

看了楼上john_lee的帖子,我意识到我前面说错了。
按作用域分,有 全局变量、文件变量、函数内变量,c++的大括号里面也可以定义变量。

a.c   b.c   c.c   三个文件,前两个里面都有个 int a; 都是全局变量。 第三个里面有个extern int a; 那么是用的哪个文件里面的呢?  所以前面我的回复是错误的。

static int a; 才是这个文件之内的,非全局的变量。参考c99的6.2.2的第三段。

无论哪个文件里面的全局变量,都是整个项目的全局变量。

6.9.2 的第二段   一个声明,如果是文件作用域,而且没有初始值,没有(typedef、extern、static、auto、register)前缀,则是个尝试性声明。如果最终没有找到声明,则给尝试声明加个声明,并赋值为0;

原文如下:
A declaration of an identifier for an object that has file scope without an initializer, and
without a storage-class specifier or with the storage-class specifier static, constitutes a
tentative definition. If a translation unit contains one or more tentative definitions for an
identifier, and the translation unit contains no external definition for that identifier, then
the behavior is exactly as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation unit, with an initializer
equal to 0.

使用特权

评论回复
18
yanghelovehuang|  楼主 | 2018-9-6 13:08 | 只看该作者
linqing171 发表于 2018-9-5 22:30
看了楼上john_lee的帖子,我意识到我前面说错了。
按作用域分,有 全局变量、文件变量、函数内变量,c++ ...

请问 这个标准我在网上也找到了 可是全英文有点吃力 有中文版的没

使用特权

评论回复
19
一路向北lm| | 2018-9-6 15:41 | 只看该作者
外部变量的关键字  可以在其它文件中调用该变量。

使用特权

评论回复
20
yanghelovehuang|  楼主 | 2018-9-6 17:40 | 只看该作者
一路向北lm 发表于 2018-9-6 15:41
外部变量的关键字  可以在其它文件中调用该变量。

这个我知道 看我的程序 我的意思是 不用extern关键字,只int a未初始化也能调用外部变量

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

156

主题

324

帖子

1

粉丝