您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
040第七章 函数09(新版) static与extern
发布时间:2021-05-02 11:31:02编辑:雪饮阅读()
Extern关键字在多文件编程的应用
在c语言中也是和其它语言一样不可能所有代码都写在一个文件中,也是可以将代码分开道不同的文件中的,然后在编译的时候进行链接。
那么extern文件在多文件编程中一般主要应用于全局变量的接收的载体。如以下实例:
main.c:
#include <stdio.h>
//提供一个全局变量(这里用来提供给p.c种的max函数使用)
int A,B;
//函数来自外部文件,所以这里必须声明
int max();
int main()
{
printf("输入两个值 用空格隔开:");
scanf("%d %d",&A,&B);
printf("\n 最大值:%d \n",max());
}
p.c:
//全局变量来自其它文件的,所以需要用extern声明
extern int A,B;
int max(){
if(A>B){
return A;
}
else{
return B;
}
}
那么其编译的时候也要将main.c和p.c都一起编译上
D:\cproject>gcc main.c p.c -o m52
D:\cproject>m52.exe
输入两个值 用空格隔开:1 3
最大值:3
Static保护
对于变量
当某个文件中的全局变量只想要当前文件使用,则可以对其使用static进行修饰,如上面的main.c修改如:
#include <stdio.h>
static int A,B;
int max();
int main()
{
printf("输入两个值 用空格隔开:");
scanf("%d %d",&A,&B);
printf("\n 最大值:%d \n",max());
}
这样,在和上面一样进行编译时候是会报错的。p.c是无法使用main.c中的A,B变量。
那么我们进一步把main.c修改为内部进行调用A,B全局变量的实例如:
#include <stdio.h>
static int A,B;
int main()
{
printf("输入两个值 用空格隔开:");
scanf("%d %d",&A,&B);
printf("A=%d B=%d",A,B);
}
这样编译就没有问题,且能正常使用
D:\cproject>gcc main.c -o m52
D:\cproject>m52.exe
输入两个值 用空格隔开:1 3
A=1 B=3
对于函数
对于函数来说,也是同样的道理,函数若被修饰为static,则会使得该函数只能在本文件内部使用。
那么接下来我们将上面的main.c和p.c求最大值的程序修改为main.c去调用p.c的max,而p.c的max又去调用main.c的m_max如:
main.c:
#include <stdio.h>
int A,B;
int max();
int m_max(int a,int b){
if(a>b){
return a;
}
else{
return a;
}
}
int main()
{
printf("输入两个值 用空格隔开:");
scanf("%d %d",&A,&B);
printf("\n 最大值:%d \n",max());
}
p.c:
extern int A,B;
int m_max(int a,int b);
int max(){
return m_max(A,B);
}
然后编译运行,可以看到这是一个正常的程序:
D:\cproject>gcc main.c p.c -o m1046
D:\cproject>m1046.exe
输入两个值 用空格隔开:1 3
最大值:1
但此时如果将main.c的m_max函数修饰为static如:
#include <stdio.h>
int A,B;
int max();
static int m_max(int a,int b){
if(a>b){
return a;
}
else{
return a;
}
}
int main()
{
printf("输入两个值 用空格隔开:");
scanf("%d %d",&A,&B);
printf("\n 最大值:%d \n",max());
}
然后编译就无法通过了,p.c无法使用main.c中的m_max函数。
其实默认情况下所有函数隐式修饰符都是extern,例如我们这里再显式的把m_max修饰符修改为extern:
#include <stdio.h>
int A,B;
int max();
extern int m_max(int a,int b){
if(a>b){
return a;
}
else{
return a;
}
}
int main()
{
printf("输入两个值 用空格隔开:");
scanf("%d %d",&A,&B);
printf("\n 最大值:%d \n",max());
}
可以看到又能正常编译运行了:
D:\cproject>gcc main.c p.c -o m1052
D:\cproject>m1052.exe
输入两个值 用空格隔开:1 3
最大值:1
那么反过来,虽然static修饰的函数不能被外部的(这里的p.c)所使用,但是可以被文件内部使用,如现在将main.c修改如:
#include <stdio.h>
int A,B;
static int m_max(int a,int b){
if(a>b){
return a;
}
else{
return a;
}
}
int main()
{
printf("输入两个值 用空格隔开:");
scanf("%d %d",&A,&B);
printf("\n 最大值:%d \n",m_max(A,B));
}
又能顺利的编译运行了:
D:\cproject>gcc main.c -o m1053
D:\cproject>m.exe
输入两个值 用空格隔开:1 3
最大值:3
利用多文件的方式进行项目的开发。
最后我们可以用一个小小的案例来实践下多文件方式项目开发,我们需要对一个字符串,当我们输入该字符串中某个字符时候就可以删除该字符串中的对应这个字符的功能,当然这个功能我们希望在例如p.c中定义,然后在main.c中进行调用删除即可。
则p.c:
//定义一个用于删除字符串中指定字符的操作
void delete_string(char str[], char ch)
{
int i, j;
for(i=j=0; str[i] != '\0'; i++)
{
if( str[i] != ch )
{
str[j++] = str[i];
}
}
//遍历结束后j就是最后一个匹配到的目标字符ch的索引,通过'\0'空白字符的转义以实现删除
str[j] = '\0';
}
main.c::
#include <stdio.h>
void delete_string(char str[], char ch);
int main()
{ char str[30]="hello world";
char c;
printf("\n 原字符串:");
for(int i=0;i<30;i++){
printf("%c",str[i]);
}
printf("\n 输入一个要删除的字符:");
scanf("%c",&c);
delete_string(str,c);
printf("\n 删除掉'%c'字符后:");
for(int i=0;i<30;i++){
printf("%c",str[i]);
}
}
Ok,这样是没有问题的:
D:\cproject>gcc main.c p.c -o m1107
D:\cproject>m1107.exe
原字符串:hello world
输入一个要删除的字符:r
删除掉'?字符后:hello wold
这里需要修缮下,就是输出时候提示本次删除的某个字符的时候(打脸),顺带提一下,引用外部函数的定义时候也可以使用extern进行修饰,当然我想默认应该也是隐式extern修饰的。如main.c修缮上面的这个bug并进行extern修饰如:
#include <stdio.h>
extern void delete_string(char str[], char ch);
int main()
{
char str[30]="hello world";
char c;
printf("\n 原字符串:");
for(int i=0;i<30;i++){
printf("%c",str[i]);
}
printf("\n 输入一个要删除的字符:");
scanf("%c",&c);
delete_string(str,c);
printf("\n 删除掉'%c'字符后:",c);
for(int i=0;i<30;i++){
printf("%c",str[i]);
}
}
现在才是真的没有问题的:
D:\cproject>gcc main.c p.c -o m1124
D:\cproject>m1124.exe
原字符串:hello world
输入一个要删除的字符:d
删除掉'd'字符后:hello worl
那么其实在函数的声明时候其实不一定非要在所有函数的定义同级,也可以是在某个函数的定义函数体内,如main.c还可以修改为这样:
#include <stdio.h>
int main()
{
extern void delete_string(char str[], char ch);
char str[30]="hello world";
char c;
printf("\n 原字符串:");
for(int i=0;i<30;i++){
printf("%c",str[i]);
}
printf("\n 输入一个要删除的字符:");
scanf("%c",&c);
delete_string(str,c);
printf("\n 删除掉'%c'字符后:",c);
for(int i=0;i<30;i++){
printf("%c",str[i]);
}
}
这样也是可以的
不过个人是不太喜欢这样的方式,感觉好low呢,而且很不规范呢。
关键字词:static,extern,函数