Переменная заголовка превращается в ноль - PullRequest
0 голосов
/ 02 марта 2020

Я использую STM32F103 и Keil для компилятора. Вот мой сводный код: есть заголовочный файл, такой как ab c .h, а в файле ab c есть переменная stati c. ab c .h выглядит так:

static uint8 a;

И в другом заголовочном файле есть функция с именем abcd.h, которая изменяет значение a. Заголовочный файл abcd.h выглядит следующим образом.

include "abc.h"

void foo()
{
    a = 0x0A;
}

Моя проблема в том, что: когда я вызываю функцию "foo" в main, "a" обнуляется, даже если я назначаю переменную "a" 0x0A в функции "foo ()". Кстати, если я определю переменную «a» с помощью extern, и проблема не возникнет. Я имею в виду, что «a» - это значение 0x0A.

Кто-нибудь может мне помочь, почему возникает эта проблема?

1 Ответ

1 голос
/ 02 марта 2020

Некоторые практические правила:

  • Никогда не объявляйте глобальные переменные. (extern единицы)
  • Никогда не объявляйте переменные внутри заголовочных файлов.

static переменные по определению не являются глобальными, но могут быть «областью действия файла», то есть видимой в файл они объявлены внутри. Точнее, видимые внутри единицы перевода они объявлены внутри, единица перевода означает конкретный файл c. c и все заголовки, которые включает в себя c файл.

Таким образом, если вы объявляете переменную static в заголовке, который включается в два разных файла. c, вы получаете несколько локальных копий переменной. Если вам повезет, вы получите ошибку компоновщика, но компоновщик также может попытаться выполнить какое-то внутреннее «искажение имени». Само значение static состоит в том, чтобы запретить доступ к переменной другим файлам.

Лучшее решение для этого - использовать функции установки / получения:

// abc.h
#ifndef ABC_H // always use "header guards"
#define ABC_H

uint8_t get_a (void);
void set_a (uint8_t n);

#endif

-

// abc.c

#include "abc.h"

static uint8_t a;

uint8_t get_a (void) 
{ 
  return a; 
}

void set_a (uint8_t n) 
{ 
  a = n; 
}

Именно так вы должны поступить в подавляющем большинстве случаев. Следует избегать использования extern, но в тех редких случаях, когда вам нужно его использовать, используйте его следующим образом:

// abc.h
#ifndef ABC_H // always use "header guards"
#define ABC_H

extern uint8_t a;

#endif

-

// abc.c
#include "abc.h"

uint8_t a;
...