se esta estrutura deve ser usada por algum outro arquivo func.c como fazer isso?
Quando um tipo é usado em um arquivo (ou seja, arquivo func.c), ele deve estar visível. A pior maneira de fazer isso é copiar e colar em cada arquivo de origem necessário.
A maneira certa é colocá-lo em um arquivo de cabeçalho e incluí-lo sempre que necessário.
devemos abrir um novo arquivo de cabeçalho e declarar a estrutura lá e incluir esse cabeçalho no func.c?
Esta é a solução que eu mais gosto, porque torna o código altamente modular. Eu codificaria sua estrutura como:
#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME
#define SOME_HEADER_GUARD_WITH_UNIQUE_NAME
struct a
{
int i;
struct b
{
int j;
}
};
#endif
Eu colocaria funções que usam essa estrutura no mesmo cabeçalho (a função que é "semanticamente" parte de sua "interface").
E normalmente, eu poderia nomear o arquivo com o nome da estrutura e usar esse nome novamente para escolher as definições dos protetores de cabeçalho.
Se você precisar declarar uma função usando um ponteiro para a estrutura, não precisará da definição completa da estrutura. Uma declaração de encaminhamento simples como:
struct a ;
Será suficiente, e diminui o acoplamento.
ou podemos definir a estrutura total no arquivo de cabeçalho e incluí-la em source.c e func.c?
Esta é outra maneira, um pouco mais fácil, mas menos modular: alguns códigos que precisam apenas de sua estrutura para funcionar ainda precisam incluir todos os tipos.
Em C ++, isso pode levar a complicações interessantes, mas isso está fora do tópico (sem tag C ++), então não vou entrar em detalhes.
a seguir, como declarar essa estrutura como externa em ambos os arquivos. ?
Não consigo entender o ponto, talvez, mas Greg Hewgill tem uma resposta muito boa em seu post Como declarar uma estrutura em um cabeçalho que deve ser usado por vários arquivos em c? .
devemos digitá-lo então como?
- Se você estiver usando C ++, não.
- Se você estiver usando C, você deve.
O motivo é que o gerenciamento de C struct pode ser uma dor: você deve declarar a palavra-chave struct em todos os lugares em que ela é usada:
struct MyStruct ; /* Forward declaration */
struct MyStruct
{
/* etc. */
} ;
void doSomething(struct MyStruct * p) /* parameter */
{
struct MyStruct a ; /* variable */
/* etc */
}
Enquanto um typedef permitirá que você escreva sem a palavra-chave struct.
struct MyStructTag ; /* Forward declaration */
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
void doSomething(MyStruct * p) /* parameter */
{
MyStruct a ; /* variable */
/* etc */
}
É importante que você ainda mantenha um nome para a estrutura. Escrevendo:
typedef struct
{
/* etc. */
} MyStruct ;
irá apenas criar uma estrutura anônima com um nome digitado, e você não poderá encaminhá-la. Portanto, mantenha o seguinte formato:
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
Assim, você será capaz de usar MyStruct em todos os lugares que deseja evitar adicionar a palavra-chave struct e ainda usar MyStructTag quando um typedef não funcionar (ou seja, declaração de encaminhamento)
Editar:
Corrigida a suposição errada sobre a declaração de struct C99, conforme devidamente observado por Jonathan Leffler .
Editar 01/06/2018:
Craig Barnes nos lembra em seu comentário que você não precisa manter nomes separados para o nome de struct "tag" e seu nome "typedef", como fiz acima por uma questão de clareza.
Na verdade, o código acima pode muito bem ser escrito como:
typedef struct MyStruct
{
/* etc. */
} MyStruct ;
IIRC, isso é realmente o que C ++ faz com sua declaração de struct mais simples, nos bastidores, para mantê-la compatível com C:
// C++ explicit declaration by the user
struct MyStruct
{
/* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;
De volta ao C, eu vi os dois usos (nomes separados e mesmos nomes) e nenhum tem desvantagens que eu conheça, então usar o mesmo nome torna a leitura mais simples se você não usar "namespaces" separados em C para structs e outros símbolos .
struct b
, mas então sua estruturaa
declara um tipo que não é usado (você provavelmente deve definir um nome de membro, talvezk
, após a chave de fechamento interna e antes do ponto e vírgula.