存储说明符extern和static

本文详细介绍了C语言中的变量存储类别,包括auto、register、extern和static,并解析了extern和static关键字的作用及应用场景。此外,还探讨了变量的不同生存期以及存储位置。

引言:

变量分类:
从变量作用域分: 全局变量和局部变量
从变量生存期分: 静态存储方式和动态存储方式

C语言中提供了存储说明符auto,register,extern,static说明的四种存储类别。四种存储类别说明符有两种存储期:自动存储期和静态存储期。其中auto和register对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块是被建立,它在该程序块活动时存在,退出该程序块时撤销。

关键字extern和static用来说明具有静态存储期的变量和函数。用static声明的局部变量只能被定义该变量的函数所识别,但是不同于自动变量的是,static变量在其函数被调用退出后,仍保留其值。下次函数被调用时,可以访问最近一次被修改后的值。

变量按存在时间分:
静态变量: 生存期为程序执行的整个过程。
动态变量: 只生存在某一段时间内。

完整的变量定义: [存储特性] [数据类型] 变量名
存储特性:
   / 自动型 auto
  /  静态型 static
  /  寄存器型 register
   / 外部型 extern
注:寄存器变量只限于整型,字符型或指针型的局部变量。
    寄存器变量是动态变量。


一.解析extern关键字
1.声明外部变量
//A.cpp
extern int i;
void main()
{
    i = 100; //试图使用B中定义的全局变量
}

//B.cpp
int i;
2.在C++文件中调用C方式编译的函数
//A.CPP
extern "C"
{
    void func();
}
void main()
{
    func();
}

//B.C
void func()
{
    printf("just a test/n");
}

二.解析static关键字
static在c里面可以用来修饰变量,也可以用来修饰函数。
 
  先看用来修饰变量的时候。变量在c里面可分为存在全局数据区、栈和堆里。其实我们平时所说的堆栈是栈而不包含对,不要弄混。
        int a ;
        main()
        {
             int b ;
             int c* = (int *)malloc(sizeof(int));
        }
    a是全局变量,b是栈变量,c是堆变量。
 
  static对全局变量的修饰,可以认为是限制了只能是本文件引用此变量。有的程序是由好多.c文件构成。彼此可以互相引用变量,但加入static修饰之后,只能被本文件中函数引用此变量。
 
  static对栈变量的修饰,可以认为栈变量的生命周期延长到程序执行结束时。一般来说,栈变量的生命周期由OS管理,在退栈的过程中,栈变量的生命也就
结束了。但加入static修饰之后,变量已经不在存储在栈中,而是和全局变量一起存储。同时,离开定义它的函数后不能使用,但如再次调用定义它的函数
时,它又可继续使用, 而且保存了前次被调用后留下的值。
 
  static对函数的修饰与对全局变量的修饰相似,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用。

<think>好的,我现在需要回答用户关于C/C++编程中形参使用的存储说明符的问题。首先,我需要明确用户的问题是什么。用户提到“形参 存储说明符 使用 方法”,所以主要是想知道在C/C++中,函数的形参是否可以应用存储说明符(如auto、register、staticextern等),以及相关的用法注意事项。 接下来,我要回顾自己关于存储说明符形参的知识。在C语言中,函数的形参默认是自动存储期的,也就是auto类型,虽然通常不需要显式写出。C++在这方面类似,但可能有更多的细节需要注意。存储说明符一般用于变量声明,控制变量的存储链接属性,比如static让变量具有静态存储期,而extern用于声明外部链接的变量。 然后,我需要确定形参是否可以使用这些说明符。根据CC++的标准,形参的声明中是否可以包含存储说明符?比如,能否将形参声明为register或static? 记得在C语言中,register关键字曾经用于建议编译器将变量存储在寄存器中,但C11标准中已经弃用了register。不过,在函数形参中是否允许使用呢?例如,像void func(register int x)这样的声明是否合法? 另外,staticextern这些存储说明符是否可以用在形参中?例如,void func(static int x)这样的写法是否正确?这应该是不允许的,因为形参的存储说明符通常只能是auto或register,而auto是默认的,所以显式使用auto可能也不被允许。 接下来,我需要查阅相关的资料或标准来确认这些信息。根据C语言的标准,函数的形参声明中可以使用register关键字,但其他存储说明符staticextern是不允许的。而在C++中,情况可能有所不同,比如C++11仍然支持register关键字,但同样不鼓励使用,并且后续版本可能也弃用了。此外,C++中是否允许其他存储说明符用于形参? 还需要考虑示例代码中的错误情况,比如引用[4]中的swap错误示例,其中tmp指针未初始化就被解引用,这可能存储说明符无关,但需要确认是否在形参使用存储说明符时可能引入类似的错误。 另外,用户提供的引用内容中,引用[2]提到C++兼容C,但在混合编程时需要注意编译链接的问题。这可能存储说明符的关系不大,但需要确保回答中不引入不相关的信息。 整理思路: 1. 形参的默认存储说明符是auto,但通常隐式使用,无需显式写出。 2. register关键字在C中可以用于形参,但已被弃用;C++中可能允许但同样不推荐。 3. staticextern存储说明符不能用于形参,会导致编译错误。 4. 形参的作用域生存期由函数调用决定,存储说明符无法改变其存储位置(如static会改变生存期,但形参的生命周期只在函数执行期间,所以无法使用static)。 5. 示例说明正确的用法错误的尝试。 然后需要验证这些点是否正确。例如,C语言中是否允许形参使用register?查阅资料发现,在C99之前,确实允许形参使用register,但在C11中register被废弃,但可能仍然允许语法上的使用,只是编译器会忽略。而C++中,register在C++17之前被弃用,之后被移除,所以在C++11中可能还可以使用,但效果C中类似。 关于staticextern,例如,尝试声明函数void func(static int x)会导致编译错误,因为存储说明符只能用于函数或文件作用域的变量,不能用于形参。 总结: 形参的存储说明符只能是auto(默认)或register(在C中,但已废弃),其他如staticextern不允许使用。在C++中,同样不允许使用除autoregister之外的存储说明符,但register在C++中也被废弃。 需要将这些内容用中文清晰地解释,结构分明,并给出示例代码说明正确错误的用法。同时,根据用户的要求,生成相关问题。 最后,确保回答中引用了提供的引用内容中的相关部分,比如引用[2]提到C++兼容C,但存储说明符的使用在两者中可能有差异,或者引用[4]中的错误示例可能与形参的存储无关,但可能需要避免类似的错误。</think>### 形参的存储说明符使用方法 在C/C++编程中,**存储说明符**(如`auto`、`register`、`static`、`extern`)主要用于控制变量的存储方式、作用域生命周期。**形参**(函数的形式参数)的存储说明符使用需遵循特定规则,以下是详细说明: --- #### 1. **默认存储说明符:`auto`** 形参默认使用`auto`存储说明符(无需显式声明),表示参数在函数调用时自动分配内存,函数结束时释放。例如: ```c void func(int x) { /* x为auto类型 */ } ``` - **作用**:形参的生命周期仅限于函数执行期间。 - **注意**:C/C++中`auto`关键字在形参中通常省略,且现代C++中`auto`已用于类型推导,与存储说明符无关[^2]。 --- #### 2. **`register`关键字(已弃用)** `register`曾用于建议编译器将变量存储在寄存器中以提高访问速度,但现代编译器已自动优化,此关键字被弃用: ```c void func(register int x) { /* 合法但无效 */ } ``` - **C语言**:C11标准弃用`register`,但仍允许语法存在。 - **C++**:C++17起移除`register`,早期版本仅保留语法兼容性[^3]。 - **注意**:实际编程中无需显式使用。 --- #### 3. **非法存储说明符:`static`、`extern`** 以下用法会导致编译错误: ```c void func(static int x); // 错误:static不能用于形参 void func(extern int x); // 错误:extern不能用于形参 ``` - **原因**: - `static`会将变量设为静态存储(生命周期与程序一致),但形参需在函数调用时动态分配。 - `extern`用于声明外部链接变量,而形参是局部变量,无法跨文件共享。 --- #### 4. **示例对比** - **正确用法**: ```c void swap(int *a, int *b) { // 形参为指针,默认auto存储 int tmp = *a; *a = *b; *b = tmp; } ``` - **错误用法**: ```c void swap_error(static int *a, static int *b) { // 编译错误 static int *tmp; // 错误:未初始化的静态指针 *tmp = *a; // 运行时错误:tmp未指向有效内存[^4] *a = *b; *b = *tmp; } ``` --- #### 5. **C/C++混合编程的注意事项** 在C++中调用C库函数时,需用`extern "C"`声明以避免名称修饰(name mangling)导致的链接错误,但存储说明符规则与C语言一致[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值