2014-12-05 56 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.