Jump to content

problema com definicao de estruturas no .c


aalex
 Share

Recommended Posts

viva, estou com um problema que não estou a conseguir resolver

tenho por objectivo manter nos ficheiro .h apenas a definição das funções, tudo o resto nos .c

o meu problema é quando defino por exemplo uma estrutura, exemplo:

typedef struct s {

....

} *ap;

se por exemplo tiver uma função que retorna um "ap" em qualquer ficheiro .h isto vai dar erro pois o tipo "ap" ainda não é conhecido já que esta no .c

alguém sabe como resolver?  🙂

Link to comment
Share on other sites

Pões o typedef no .h (que é incluido pelos outros que precisarem), mas a declaração da estrutura no .c... Isto é:

No .h:

typedef struct s *ap;

e no .c (que tem de incluir o .h):

 struct s {
....
};

PS: Desta forma todos os ficheiros que incluam o .h vão conhecer o tipo ap, mas não podem aceder aos campos. Todas as funções que acedem aos mesmos têm de estar no .c que define a struct. Se precisares de aceder aos campos em funções de outros .c, então tens de pôr toda a declaração no .h.

Link to comment
Share on other sites

Mantendo a definição da estrutura num .c podes introduzir um "tipo incompleto" no ficheiro .h

struct s; // tipo incompleto; podes usar ponteiros para ele
struct s *fx(void);

Mas o melhor é meteres a definição da estrutura no ficheiro .h.

E, já agora, meteres a definição das funções nos ficheiros .c, mantendo apenas os protóptipos das mesmas no ficheiro .h.

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Link to comment
Share on other sites

não existe uma outra forma de colocar as estruturas no .c sem a necessidade de colocar os "protótipos" no .h?

Uma outra solução seria usares void* nos parametros das funções.

Na implementação da função convertes o void* para struct whatever * mais ou menos como se faz para a função de comparação usada no qsort

// header file
void *fx(void *);

// implementation file .c
struct foo { /* whetever */ };
void *fx(void *data) {
    struct foo *value, *parm = data;
    /* usa parm->membro para atribuir valores a value->membro */
    return value;
}

// usage
#include "foo.h"
void *opaque = fx(NULL);
while (opaque) opaque = fx(opaque);

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Link to comment
Share on other sites

o chato é depois ter de fazer imensos castings

Não, não tens de fazer casting nenhuns se construires o código a pensar nisso. No meu exemplo acima, por exemplo, não há nenhum cast.

Em C, o tipo void* é compativel com ponteiros para qualquer tipo de objecto; ou seja o compilador faz as conversões necessárias (se houver) automagicamente e podes aceder ao "tipo base" normalmente. Estás a compilar C++, talvez?

#include <stdio.h>
#include <stdlib.h>
// outro exemplo
struct whatever {
   int data;
   /* ... */
};

int cmp(const void *a, const void *b) {
   const struct whatever *aa, *bb;
   // valores de tipo void * são compativeis com objectos de tipo struct whatever *
   // por isso as atribuições seguintes são válidas sem cast nenhum (atencão ao const)
   aa = a;
   bb = b;
   return aa->data - bb->data;
}

int main(void) {
   struct whatever x[4] = {{7}, {4}, {9}, {2}};
   qsort(x, 4, sizeof *x, cmp);
   if (x->data != 2) puts("Oops");
   return 0;
}

Podes ver que o ideone não se chateia pela ausencia dos casts.

Em C, muitos casts são completamente desnecessarios (para não dizer que são um erro) e indicam que o autor do codigo não sabe "falar" C --- ou que esta a tentar escrever codigo fonte para mais que uma linguagem. Onde os casts sao necessarios e nas funcoes declaradas em <ctype.h>, nalguns casos de printf() ("%p"), abuso da linguagem, e pouco mais.

Talvez te interesse ler um artigo do Richard Heathfield em que explica porque os casts sao desnecessarios e ate errados. (Nota: o artigo nao se encontra disponivel no endereco original, por isso o link vai para o wayback archive.)

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Link to comment
Share on other sites

existe alguma razão para não quereres colocar o

typedef struct s {
....
} *ap;

no .h ???

Normalmente eu uso isso em API's em que não quero que quem a vai usar saiba o que está na estrutura 🙂   Por isso apenas ponho a typedef no header, e a declaração da struct no .c, tal como disse no meu post. Normalmente para Handlers e coisa e tal...  Muitas vezes também os defino como void *, como disse o pmg.

Link to comment
Share on other sites

Normalmente eu uso isso em API's em que não quero que quem a vai usar saiba o que está na estrutura 🙂   Por isso apenas ponho a typedef no header, e a declaração da struct no .c, tal como disse no meu post. Normalmente para Handlers e coisa e tal...  Muitas vezes também os defino como void *, como disse o pmg.

então usa os tipos opacos ... não existe necessidade de void *

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.