static int 和 int 你所踩过的坑

本文深入探讨了C语言编程中遇到的bug,特别是在使用Yacc自动生成器进行语法分析器开发时的问题。文章详细解释了static int与int的区别,强调了静态变量在函数调用中的作用。

对于一个刚进入大学就接触C语言的我,感觉对C还是比较了解的,但是在做编译原理大作业语法分析器的时候使用了Yacc自动生成器,虽然是自动生成,但是需要写一个辅助函数,就在写这个辅助函数的时候出现了这个特别奇怪的bug

先上代码

int yylex(void){
    static int done = 0;
    static int c;
    static int flag=0;
    if(done)return 0;
    if(flag==1){
        flag=0;
        if(c!=' '){
            if(c=='\n')done=1;
            return c;
        }
    }
    while((c=getchar())==' ');
    if(isdigit(c)){
        yylval = c-'0';
        while(isdigit(c=getchar())){
        yylval *=10;
        yylval +=c-'0';
    }
    flag=1;
    return (NUM);
    }
    else if(c=='\n')
    done=1;
    return c;
}

bug 比较复杂,在这里就不赘述了,这里进入到咱们今天的重点,static  int 和 int

静态变量就是要在程序的一开始就要载入,也就是它不是随着程序运行的时候而改变的

static int 和 int 在main函数中区别不大,但是如果涉及到子函数,那么区别就很大了。

static 可以看成是全局变量。

也就是说上面的代码中的状态变量都会随着函数的每一次调用而赋上初值

但是这个函数的初衷是要利用这些状态变量来进行一些跳转啊,循环啊之类的操作,所以这里需要设置成static

<think> 首先,用户的问题是关于理解 C 语言中 static int int 的区别。从系统指令中,我知道必须使用中文回答,结构化清晰,并确保回答真实可靠。参考了提供的引用:[1]、[2]、[3] [4],这些引用讨论了 static int int 在作用域、生命周期、存储位置等方面的区别。 关键点从引用中提取: - 引用[1]:强调 static int int 在作用域、生命周期、存储位置的区别。 - 引用[2]:在 C++ 中,类似区别包括作用域(static int 有全局作用域或函数内局部作用域)、生命周期(static 变量生存期是整个程序运行时间)、存储位置(静态存储区)。 - 引用[3]:通过代码示例展示全局变量局部变量中 static int int 的区别。例如: - 全局 int:所有函数可见。 - 全局 static int:文件作用域,只在当前文件可见。 - 局部 int:函数内声明,每次调用重新初始化。 - 局部 static int:函数内声明,但只在第一次调用初始化,之后保留值。 - 引用[4]:代码展示函数中 static int 变量如何保留值跨函数调用。 总结区别: 1. **作用域**: - `int`:当声明为局部变量时,只在定义的块(如函数)内可见;全局变量在整个程序可见(除非有 static)。 - `static int`:如果声明为全局变量,具有文件作用域(只在当前文件可见);如果声明在函数内,具有块作用域(只在函数内可见),但由于静态特性,值保留。 2. **生命周期**: - `int` 局部变量:自动存储期,在函数调用时创建,调用结束时销毁。 - `static int`:静态存储期,在程序启动时初始化一次,直到程序结束才销毁。 3. **存储位置**: - `int` 局部变量:通常存储在栈上。 - `static int`:存储在静态存储区(全局区或 BSS 段)。 4. **初始化**: - `int` 局部变量:如果不显式初始化,值是未定义的(垃圾值)。 - `static int`:如果不显式初始化,自动初始化为 0(对于基本类型)。 另外,从引用[3]的代码: - 全局 `int a=0;`:所有文件可见(如果声明在头文件中)。 - 全局 `static int a=0;`:只在当前文件可见,防止链接冲突。 - 局部 `int a=0;`:每次函数调用,重置为 0。 - 局部 `static int a=0;`:只在第一次调用初始化,之后保留上一次的值。 回答结构应该清晰: - 先介绍基本概念。 - 然后分点解释区别:作用域、生命周期、存储位置、初始化、使用场景。 - 使用 LaTeX 格式:行内数学表达式用 $...$,独立公式用 $$...$$(但这里可能不需要数学公式,除非提到地址或值)。 - 末尾自然地添加引用标识。 - 最后生成相关问题。 系统指令说:回答中引用的段落末尾自然地添加引用标识。所以,当我引用特定概念时,如在解释部分,可以添加 [^n]。 生成相关问题: - 类似于示例,基于主题生成 2-3 个相关问题。 - 例如:如何选择使用 static intintstatic int 的优缺点?在 C++ 中有什么区别? (since reference [2] is about C++, but user asked for C language) 用户明确说“我想了解static intint的区别”,并在引用中提到 C 语言 C++,但焦点是 C 语言(引用[1] and [3])。 确保回答真实可靠:我得基于标准 C 语言知识。 </think> ### static int int 的区别 在 C 语言中,`int` `static int` 是两种声明变量的方式,但它们在作用域、生命周期、存储位置等方面有显著差异。理解这些区别对于编写高效、可维护的代码至关重要。以下我将从多个维度逐步解释两者的不同之处,基于标准 C 语言规范(ISO C99/C11)提供的引用内容。 #### 1. **作用域(Scope)** - **`int`**: - 当声明为局部变量(在函数内部)时,作用域仅限于该函数或代码块内。 - 当声明为全局变量(在函数外部)时,作用域覆盖整个程序(所有文件可见),但如果未使用 `extern` 关键字,可能导致链接冲突[^1][^3]。 示例代码片段(引用[3]): ```c #include <stdio.h> int a = 0; // 全局 int 变量,所有函数可见 int add() { printf("%d", a++); return 0; } // main 函数调用 add() 时,a 的值会累积 ``` - **`static int`**: - 当声明为全局变量(在函数外部)时,作用域限制在当前文件内(文件作用域),其他文件无法访问,这有助于避免命名冲突。 - 当声明为局部变量(在函数内部)时,作用域仍限于该函数内,但它的值在函数调用间持久化[^1][^3]。 示例代码片段(引用[3][4]): ```c #include <stdio.h> static int a = 0; // 全局 static int 变量,只在当前文件可见 int add() { static int b = 0; // 局部 static int 变量,作用域在 add() 内 printf("%d", b++); // b 的值在多次调用中保留 return 0; } ``` #### 2. **生命周期(Lifetime)** - **`int`**: - 局部变量:具有自动存储期,在函数调用时创建,函数结束时销毁。变量的值每次调用时重置。 - 全局变量:具有静态存储期,在程序启动时初始化一次,直到程序结束才销毁。 示例(引用[3]): ```c #include <stdio.h> int add() { int a = 0; // 局部 int,每次调用重置为 0 printf("%d", a++); // 输出总是 0 return 0; } ``` - **`static int`**: - 无论全局或局部,都具有静态存储期。变量在程序启动时初始化一次(如果未显式初始化,则自动初始化为 0),生命周期覆盖整个程序运行时间。 示例(引用[4]): ```c #include <stdio.h> void function() { static int a = 3; // 局部 static int,只在第一次调用初始化 printf("a=%d\n", a); a += 3; // 值在多次调用中累积 } int main() { function(); // 输出:a=3, 然后 a=6 function(); // 输出:a=6, 然后 a=9 return 0; } ``` #### 3. **存储位置(Storage Location)** - **`int`**: - 局部变量:存储在栈(stack)上,内存分配释放快速,但频繁操作可能导致栈溢出。 - 全局变量:存储在静态存储区(如 .data 或 .bss 段),内存位置固定。 - **`static int`**: - 总是存储在静态存储区(static storage),与全局变量相同。内存占用稳定,但可能导致较大的程序内存占用[^1][^2]。 #### 4. **初始化(Initialization)** - **`int`**: - 局部变量:如果不显式初始化,值是未定义的(可能为随机垃圾值),容易引发错误。 - 全局变量:如果不显式初始化,自动初始化为 0。 - **`static int`**: - 总是自动初始化为 0(如果未显式赋值)。例如,声明 `static int x;` 等价于 `static int x = 0;`。这提升了代码的可靠性[^1][^3]。 #### 5. **使用场景优缺点** - **`int`**: - **优点**:适合临时变量,内存高效,适用于高频调用的函数。 - **缺点**:全局 `int` 可能导致命名冲突;局部 `int` 的值不持久,不适合跨调用共享数据。 - **常见用途**:循环计数器、函数参数。 - **`static int`**: - **优点**:适合需要维持状态的场景(如计数器、缓存),避免全局变量的污染;文件作用域保护数据封装。 - **缺点**:占用静态内存,可能导致内存浪费;多线程环境下需加锁以防止竞态条件。 - **常见用途**:单例模式、模块内部计数器(如引用[4] 的示例)[^1][^2]。 #### 总结 - `int` 是基础变量声明,侧重局部性临时性。 - `static int` 添加了静态属性,强调持久性作用域控制。选择时需考虑: - 如果需要变量在函数调用间保持状态,用 `static int`。 - 如果变量只在函数内临时使用,用普通 `int`。 - 对于全局变量,优先 `static int` 来限制作用域。 以上解释基于 C 语言标准,实际在 C++ 中类似,但 C++ 的 `static` 在类中还有其他语义[^2]。如需更深入讨论内存模型或性能影响,可参考相关问题。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值