2014-12-05 30 views
1

所以我被打约试图了解使用静态变量,显然我的理解是还没有应用,因为我不明白以下是如何操作:访问和修改局部静态变量

主要叫我该吐出奏x和y中的内容从other.c

//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不会导致警告/错误? 如何/在哪里存储设置为y的值,当它等于0和1在主?

如果我想通过意外地访问其范围之外的静态变量而导致问题,我该怎么做不同?

+0

作为一般规则,确保头文件中的任何变量声明被声明为'extern'。 – 2014-12-05 05:52:53

回答

1

根据C标准(6.9外部定义)

5外部的定义是,也是一个函数(比内联定义其他)或 对象的 定义的外部声明。 如果在 中使用一个表达式(除了作为sizeof运算符 的操作数的一部分,其结果是一个整数常量),则在整个程序 中的某处应该有一个外部定义标识符; 否则,不应有多于one.161)

但是编译器不能检查与外部链接的标识符是否被定义多于一个的时间。这是一个链接器,做这样的检查。所以你应该看到链接器的选项。有时默认情况下,他们只是简单地消除超级流量定义。然而有时候这种行为变得没有定义。

一般来说有三种可能性。 第一个是链接器发出错误。 第二个是链接器只保留外部对象的一个​​定义。 第三个是链接器将具有外部链接的对象的所有重复项作为具有内部链接的对象。

在你的情况下,似乎链接器只保留名称为x的对象的一个​​定义。

对于因关键字static而声明的内部链接的变量y,那么两个编译单元与main和func都有自己的对象y。因此,在主要的第一个编译单元中,您更改了一个对象y,而其他编译单元中的函数func更改了它自己的对象y,尽管存在y是同一对象的错觉。

+0

你如何确定链接器只保留一个定义而不是第三种可能性? – LogicTom 2015-01-15 10:14:07

0

当头文件中有一个静态变量时,每次包含它时都会创建一个新对象。它的范围将只针对该模块(或文件)。由于在一个文件中(other.c),您正在递增,您看到的值正在递增,而在另一个(main.c)中,您不递增,因此该值始终为0.