所以我正在尝试理解静态变量的使用,显然我的理解还不完全,因为我不明白以下是如何操作的:
主调用我的有用函数,从other.c
吐出x和y的内容//main.c
#include <stdio.h>
#include <stdint.h>
#include "other.h"
int main (void)
{
printf("Main - X: %d, Y: %d\r\n\n",x,y);
func();
printf("Main - X: %d, Y: %d\r\n\n",x,y);
func();
printf("Main - X: %d, Y: %d\r\n\n",x,y);
printf("Main - X: %d, Y: %d\r\n\n",++x,++y);
return 0;
}
other.h
//other.h
void func(void);
uint8_t x;
static uint8_t y;
other.c
//other.c
#include <stdio.h>
#include <stdint.h>
#include "other.h"
void func(void)
{
x += 1;
y += 2;
printf("Func - X: %d Y: %d\r\n",x,y);
}
我的输出:
Main - X: 0, Y: 0
Func - X: 1 Y: 2
Main - X: 1, Y: 0
Func - X: 2 Y: 4
Main - X: 2, Y: 0
Main - X: 3, Y: 1
我无法解释的两件事;为什么从main访问y不会导致警告/错误? 当在main中等于0和1时,如何/在哪里存储设置为y的值?
如果我想通过意外访问范围之外的静态变量而导致问题,我应该做些什么呢?
答案 0 :(得分:1)
根据C标准(6.9外部定义)
5外部定义是外部声明,也是一个 函数的定义(内联定义除外)或 宾语。 如果使用通过外部链接声明的标识符 表达式(除了作为sizeof运算符的操作数的一部分之外) 其结果是整数常量),在整个程序中的某个地方 标识符只有一个外部定义; 否则,不得超过一个.161)
然而,编译器无法检查是否多次定义了具有外部链接的标识符。链接器是进行此类检查的。所以你应该看到链接器的选项。有时默认情况下,它们只是消除了超级定义。但有时候这种行为是未定义的。
一般来说,有三种可能性。 第一个是链接器发出错误。 第二个是链接器只保留外部对象的一个定义。 第三个是链接器将具有外部链接的对象的所有副本作为具有内部链接的对象。
在您的情况下,链接器似乎只保留名称为x的对象的一个定义。
对于具有内部链接的变量y,由于它使用关键字static声明,所以两个编译单元一个主要和另一个与func有自己的对象y。因此,在main中的第一个编译单元中,您更改一个对象y,而其他编译单元中的函数func更改其自己的对象y,尽管存在y是同一对象的错觉。
答案 1 :(得分:0)
如果在头文件中有静态变量,则每次包含它时都会创建它的新对象。它的范围仅适用于该模块(或文件)。因为在一个文件(other.c
)中你正在递增它,你看到值正在递增而在另一个文件中main.c
)你没有递增它,因此值总是为0。