Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как сослаться на структуру typedef struct?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Димон Безпарольный
В одном хидере объявлена структура:

Код
typedef struct ADC_my2 {            //Структура для хранения сырых значений
    uint16_t    ADC_CH0;            //
    uint16_t    ADC_CH1;            //
    uint16_t    ADC_CH2;            //
    uint16_t    ADC_CH3;            //
    uint16_t    ADC_CH4;            //    
    uint16_t    ADC_CH5;            //
    uint16_t    ADC_CH6;            //
    uint16_t    ADC_CH7;            //    
}ADC_my;                            //
ADC_my ADC_RAW;                        //


Для того, чтобы были доступны ее элементы из другого файла нажно в его хидере объявить эту структуру как extern. Если я правильно понимаю. Как это сделать?
Genadi Zawidowski
В хидеое должно быть так:
extern ADC_my ADC_RAW;

И только в одном из файлов должна быть еще такая строка:
ADC_my ADC_RAW

Цитата
Как это сделать

любым текстовым редактором.
scifi
Цитата(Genadi Zawidowski @ Jun 20 2017, 12:29) *
В хидеое должно быть так:
extern ADC_my ADC_RAW;

Совсем не обязательно в хедере. Если нужно только в одном месте, то прямо в исходнике, можно даже внутри функции. Ну а если в нескольких местах, то в хедере удобнее.
Димон Безпарольный
Не получается однако. Я так уже пробовал. Потому и спросил.

Код
../Src/stm32l1xx_it.c(91): error:  #20: identifier "ADC_my" is undefined
novikovfb
Цитата(Димон Безпарольный @ Jun 20 2017, 13:37) *
Не получается однако. Я так уже пробовал. Потому и спросил.

Код
../Src/stm32l1xx_it.c(91): error:  #20: identifier "ADC_my" is undefined

что-то Вы умалчиваете.
В хедере должно быть объявление типа структуры и extern объявление переменной. Этот хедер должен подключаться во все файлы, где используется эта структура. В одном из файлов должна быть размещена эта струкутра, т.е. объявление переменной без extern, хедер этому мешать не будет.
Mareng
Цитата(Димон Безпарольный @ Jun 20 2017, 16:37) *
Не получается однако. Я так уже пробовал. Потому и спросил.


Возможно влияет последовательность компиляции файлов
novikovfb
Цитата(Mareng @ Jun 20 2017, 13:41) *
Возможно влияет последовательность компиляции файлов

не может быть
Димон Безпарольный
Цитата(novikovfb @ Jun 20 2017, 12:40) *
что-то Вы умалчиваете.
В хедере должно быть объявление типа структуры и extern объявление переменной. Этот хедер должен подключаться во все файлы, где используется эта структура. В одном из файлов должна быть размещена эта струкутра, т.е. объявление переменной без extern, хедер этому мешать не будет.

Возможно умалчиваю потому, что не понимаю механизма.

В каком хедере должно быть объявление типа структуры? У меня в одном хедере размещена структура, в другом - я на нее сослался с помощью extern. Но получил ошибку (выше). Что я сделал неправильно?
novikovfb
Цитата(Димон Безпарольный @ Jun 20 2017, 13:52) *
Возможно умалчиваю потому, что не понимаю механизма.

В каком хедере должно быть объявление типа структуры? У меня в одном хедере размещена структура, в другом - я на нее сослался с помощью extern. Но получил ошибку (выше). Что я сделал неправильно?

Ничего волшебного. Хедеры используются исключительно для удобства и уменьшения вероятности ошибки при переписывании. Компилятор последовательно просматривает текст программы, подключает все хедеры в том порядке, в котором они упомянуты в #include. Видит объявление типа структуры - запоминает, что это такое. Когда видит extern ADC_my ADC_RAW - запоминает, что где-то есть такая структура уже известного типа ADC_RAW. Когда видит ADC_my ADC_RAW - проверяет, не противоречит ли это ранее увиденной extern ADC_my ADC_RAW и отводит место в памяти для этой структуры.
Димон Безпарольный
Цитата(novikovfb @ Jun 20 2017, 12:59) *
Ничего волшебного. Хедеры используются исключительно для удобства и уменьшения вероятности ошибки при переписывании. Компилятор последовательно просматривает текст программы, подключает все хедеры в том порядке, в котором они упомянуты в #include. Видит объявление типа структуры - запоминает, что это такое. Когда видит extern ADC_my ADC_RAW - запоминает, что где-то есть такая структура уже известного типа ADC_RAW. Когда видит ADC_my ADC_RAW - проверяет, не противоречит ли это ранее увиденной extern ADC_my ADC_RAW и отводит место в памяти для этой структуры.

Спасибо. Почему тогда ругается на extern ADC_my ADC_RAW; ?

Цитата
../Src/stm32l1xx_it.c(91): error: #20: identifier "ADC_my" is undefined
Сергей Борщ
QUOTE (Димон Безпарольный @ Jun 20 2017, 13:01) *
Спасибо. Почему тогда ругается на extern ADC_my ADC_RAW; ?
Потому что к моменту, когда он встретил упоминание этого типа он еще не видел заголовочного файла с объявлением этого типа. Хотите, чтобы он ожидал это объявление позже - пишите extern struct ADC_my ADC_RAW;
Димон Безпарольный
Цитата(Сергей Борщ @ Jun 20 2017, 13:06) *
Потому что к моменту, когда он встретил упоминание этого типа он еще не видел заголовочного файла с объявлением этого типа. Хотите, чтобы он ожидал это объявление позже - пишите extern struct ADC_my ADC_RAW;

Вот какие тонкости оказывается. Получилось. Спасибо.

Но при обращении к такой структуре:

Цитата
ADC_NMEA(ADC_RAW.ADC_CH0)


получаю ошибку:

Цитата
../Src/stm32l1xx_it.c(152): error: #70: incomplete type is not allowed

novikovfb
Цитата(Димон Безпарольный @ Jun 20 2017, 14:08) *
Вот какие тонкости оказывается. Получилось. Спасибо.

Но при обращении к такой структуре:



получаю ошибку:

Объявление типа структуры надо подключать везде, где она используется. Компилятор обрабатывает каждый си-шный файл по отдельности, не запоминая результатов компиляции ранее обработанных файлов.
Димон Безпарольный
Цитата(novikovfb @ Jun 20 2017, 13:15) *
Объявление типа структуры надо подключать везде, где она используется. Компилятор обрабатывает каждый си-шный файл по отдельности, не запоминая результатов компиляции ранее обработанных файлов.

Подскажите, что конкретно надо написать. Что - то не получается.
Непомнящий Евгений
Код
// a.h
typedef struct A {int f; } AA;
extern AA a;

//b.cpp
#include "a.h" // тут будет включен полный текст файла а.h, в результате компилятор узнает, что есть тип АА и есть переменная а этого типа

// если бы мы не писали "extern AA a" в a.h, то это объявление пришлось бы писать везде, где нужна переменная "а".
// Если она нужна всего в одном файле, то стоит ее там и определить, причем как "static AA a;" static означает, что переменная локальная для файла
void f() { a.f = 2; }

// c.cpp
#include "a.h" // компилятор работает с каждым файлом отдельно. Тут он уже забыл про АА и а, надо включить снова

AA a; // выше мы только объявили "а". Где-то должно быть и определение, иначе будет ошибка линковки. Определение может быть в любом файле проекта
// но только в одном - если мы в a.h уберем extern, то объявление окажется в двух файлах (b.cpp и c.cpp), в результате будет ошибка линковки

void g() { a.f += 1; }


А вообще наройте книжку по Си и почитайте, это ж основы. Сложно учить язык методом проб и ошибок sm.gif
Lagman
В .h (для примера main.h) файле обычно находится объявление типа для структуры
Цитата
typedef struct { //Структура для хранения сырых значений
uint16_t ADC_CH0; //
uint16_t ADC_CH1; //
uint16_t ADC_CH2; //
uint16_t ADC_CH3; //
uint16_t ADC_CH4; //
uint16_t ADC_CH5; //
uint16_t ADC_CH6; //
uint16_t ADC_CH7; //
} ADC_my; //

обрамляя при этом файл main.h
Код
#ifndef MAIN_H
#define MAIN_H
... содержимое заголовочного файла ...
#endif


В си файле где определяется структура
Цитата
#define main.h
......
ADC_my ADC_RAW; //
.....


В других сишных файлах где используется глобальная структура определенная в другом файле
Цитата
#define main.h
......
extern ADC_my ADC_RAW;
.....

Я создаю проекты не включая все си файлы в один си файл, видел как делают некоторые в один main.c включают много #define second.c и другие сишные файлы.
novikovfb
Цитата(Lagman @ Jun 20 2017, 15:16) *
В других сишных файлах где используется глобальная структура объявленная в другом файле

extern ADC_my ADC_RAW; лучше перенести в хедер, как и все объявления глобальных переменных. Компилироваться и даже работать будет и так и эдак, но риск влепить малозаметную ошибку в хедере меньше.
Lagman
Цитата(novikovfb @ Jun 20 2017, 14:27) *
extern ADC_my ADC_RAW; лучше перенести в хедер, как и все объявления глобальных переменных. Компилироваться и даже работать будет и так и эдак, но риск влепить малозаметную ошибку в хедере меньше.

Можно, только я не знаю что будет если вначале идет extern ADC_my ADC_RAW; а потом появляется ADC_my ADC_RAW;
Димон Безпарольный
Да, спасибо. Так все заработало.

В хидере:

Код
typedef struct ADC_my2 {            //Структура для хранения сырых значений
    uint16_t    ADC_CH0;            //
    uint16_t    ADC_CH1;            //
    uint16_t    ADC_CH2;            //
    uint16_t    ADC_CH3;            //
    uint16_t    ADC_CH4;            //    
    uint16_t    ADC_CH5;            //
    uint16_t    ADC_CH6;            //
    uint16_t    ADC_CH7;            //    
}ADC_my;                            //


Там, где структура заполняется:

Цитата
ADC_my ADC_RAW;


В остальных местах где использую структуру подгружаю хидер и пишу:

Цитата
extern ADC_my ADC_RAW;
Lagman
Цитата(Димон Безпарольный @ Jun 20 2017, 14:32) *
Да, спасибо. Так все заработало.

Но книжки надо читать, а то так и будете проклинать HAL не понимая что там происходит sm.gif
novikovfb
Цитата(Lagman @ Jun 20 2017, 15:30) *
Можно, только я не знаю что будет если вначале идет extern ADC_my ADC_RAW; а потом появляется ADC_my ADC_RAW;

хорошо будет: компилятор увидит, что тип тот же самый и спокойно это обработает. А если объявить
extern ADC_my ADC_RAW;
и
DAC_my ADC_RAW;
, то компилятор ткнет носом в ошибку.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.