Função .(ponto) e -> (seta) em C [RESOLVIDO]

1. Função .(ponto) e -> (seta) em C [RESOLVIDO]

Pedro Rafael
Pedro Rafael

(usa Fedora)

Enviado em 19/05/2008 - 09:16h

qual o sentido dessas funções. No livros "C Completo e total" ele passa muito rapidamente sobre essas funções, onde ele fala que ponto e seta "referenciam elementos individuais de estruturas de união. O operador ponto é usado quando se está referenciando a estrutura ou união real. O operador seta é usado quando um ponteiro para uma estrutura é usado."

obs.: Já entendi o que é um ponteiro e os seus operadores * &.


obrigado desde já pessoal.


  


2. MELHOR RESPOSTA

Elgio Schlemer
elgio

(usa OpenSuSE)

Enviado em 19/05/2008 - 09:36h

Por estas e outras que não gosto do livro C completo e total. :-D

Bom, tu disse que já sabe ponteiros. Vou confiar nisto :-D

Quando eu defino uma estrutura:
struct LIXO {
int a;
int b;
};

E uma variavel para ela:

struct LIXO x;

Se usa o ponto para acessar o membro dela:

x.a = 200;
O C calcula o deslocamento em memória de onde está o membro a da variavel x. x é do tipo struct e tem tamanho de 8 (um sizeof sobre x retorna 8 bytes pois internamente ela tem dois ints de 4)

Mas quando se cria UM PONTEIRO para a estrutura:

struct LIXO *p;

p NÃO É DO TIPO struct LIXO, p é do tipo ponteiro. O tamanho de p é 4 bytes.

Fazer:

p.a = 300;

Vai dar erro, pois p NÃO É ESTRUTURA e não tem membro a (p APONTARÁ para uma estrutura).

Mesmo que eu faça:

p = &x;

(agora p aponta para a minha variável x).

Ainda assim eu não posso fazer um p.a

Como p é ponteiro, SEMPRE que eu desejo acessar o conteúdo, ou seja, o que tem dentro de p, devo usar asterisco, certo? Logo para acessar o membro a devo fazer:

(*p).a = 400;

Isto funciona! Ou seja, a posição de memória para onde p aponta, no seu campo a receberá o valor 400.

Veja este exemplo COMPLETO:
struct LIXO {
int a;
int b;
};

int main ()
{
struct LIXO *p;
struct LIXO x;

p = &x;

(*p).a = 200;

printf("%i\n", x.a);

}

Ok, ok. Mas onde entra a setinha???

Simples. O pessoal do C achou que era muito trabalho usar (*p).a. Muito estranho, mesmo que correto. Logo inventou esta outra alternativa:

p->a = 400;

Isto É O MESMO, EXATAMENTE A MESMA COISA, do que

(*p).a = 400;

[]'s

3. :)

sombriks
sombriks

(usa Slackware)

Enviado em 19/05/2008 - 12:16h

muito bela aexplicação elgio!

roubando um pouco o foco da thread, typedefs tem implicações negativas em memória ou performance? a sintaxe fica tão mais humana (Registro r ao invés struct _Registro r) se eu der typedef no meu struct, por que é tão difícil ver um desses nos fontes do kernel?


4. typedef

Elgio Schlemer
elgio

(usa OpenSuSE)

Enviado em 19/05/2008 - 13:35h

typedef não muda nada, absolutamente nada. Seu uso é justamente para facilitar.

Sem typedef:

struct LIXO {
...
};

struct LIXO *a;

a = (struct LIXO *) malloc (sizeof (struct LIXO));

Sempre struct LIXO o que é INCOMODO.

DETALHE!!!:

struct LIXO {
...
};

LIXO p;

Funciona em compiladores c++. Se tu chamou teu fonte de .cpp isto é C++ e irá compilar sem problemas. Mas o C ANSI não aceita.

Com typedef:

typedef struct {
...
} LIXO;

LIXO *a;
a = (LIXO *) malloc (sizeof (LIXO));

Agora apenas o nome.

EM C ANSI tem um inconveniente (facilmente resolvido) com o typedef:

typedf struct {
...
LIXO *prox;
} LIXO;

Caso de lista encadeada. Em alguns compiladores vai dar erro no prox pois neste momento ainda não existe o tipo LIXO. Isto pode ser resolvido assim:

typedf struct LIXO2 {
...
struct LIXO2 *prox;
} LIXO;

typedef é muito mais natural e, como disseste, mais "humano"


5. ae

João Marcos Menezes
stremer

(usa Arch Linux)

Enviado em 19/05/2008 - 13:48h

elgio, como sempre detonando nas explicações. Algum dia ainda aprendo a explicar as coisas igual a você :)

sombriks: Quanto a não ver muito no kernel, acredito que seja por causa de algum problema de incompatibilidade com algum compilador mais antigo, já que tem mto módulo do kernel que não precisa de nenhuma modificação para compilar em outras plataformas. Ou eu estou errado nisso elgio??? me corrijam se estiver errado.


6. Re: Função .(ponto) e -> (seta) em C [RESOLVIDO]

Elgio Schlemer
elgio

(usa OpenSuSE)

Enviado em 19/05/2008 - 13:53h

Ai eu já não sei stremer.

Pelo que entendo typedef é tão padrão quanto struct.

Posso pesquisar, mas talvez tenha alguma coisa a ver com simbolos. No kernel os módulos exportam definições um para o outro (é comum tu ver citações com a diretiva extern)...

Talvez o typedef seja quase um define e não possa ser exportado, dai a preferência em usar struct...

Não sei, como disse é uma suposição.


7. Re: Função .(ponto) e -> (seta) em C [RESOLVIDO]

Elgio Schlemer
elgio

(usa OpenSuSE)

Enviado em 19/05/2008 - 13:56h

Acabei de pedir ajuda aos universitários. :-D


8. O que me disseram...

Elgio Schlemer
elgio

(usa OpenSuSE)

Enviado em 19/05/2008 - 14:11h

"
É simples. O typedef torna o código ilegível em muitos casos (pois eles abstraem o tipo), já que tu não sabe se o typedef é escalar, struct, ou qualquer outra coisa. Typedefs existem no kernel para tipos realmente opacos, para casos de brutal não-portabilidade, e novos tipos onde o nome é idêntico aos tipos do C99, por exemplo. Mais informações sobre isso se encontra em kernel/CodigStyle (ao qual eu traduzi uns 80% já, mas me falta tempo pra acabar e publicar).


Abraço
Mauad
"


9. Re: Função .(ponto) e -> (seta) em C [RESOLVIDO]

Elgio Schlemer
elgio

(usa OpenSuSE)

Enviado em 19/05/2008 - 14:19h

Programadores para kernel respeitam um padrão. Nele se proibe este tipo de typedef pelas razões descritas. Este documento é chamado de CodgingStyle e uma cópia dele pode ser lida aqui (sessão 5 trata dos typedefs)

http://lxr.linux.no/linux/Documentation/CodingStyle


10. Olha este comentário:

Elgio Schlemer
elgio

(usa OpenSuSE)

Enviado em 19/05/2008 - 15:41h

Sobre os typedefs eu postei em uma lista de programadores de kernel. Aprendi MUITA COISA e irei até mudar minhas atitudes enquanto programador. Veja esta resposta:

"
Olá Elgio,

O principal problema do typedef é que ele esconde o tipo real da variável. Isto permite que o programador (muitas vezes sem saber) passe grandes structs pela pilha como parametro ou retorno de função.

Além disso temos problemas de portabilidade, como já foi mensionado ai em cima e no documento.

Existem usos elegantes para o typedef. O FILE é um exemplo disso, ele abstrai uma estrutura que representa o arquivo que está sendo acessado e todas as operações nesse FILE são feitas por funções da biblioteca na qual ele está definido.

O problema é que muitas vezes o programador usa typedef simplesmente para esconder um nome grande/"feio" da struct e isso não é uma boa prática.

Já vi casos em que o programador nem dava nomes às structs, simplesmente cada struct ganhava um typedef. ;-)

Na dúvida, não se usa typedef! ;-)

-veiga
"

Com a grande observação de que no PENÚLTIMO parágrafo eu me enxerguei 100%!!

hehehehe


11. legal

João Marcos Menezes
stremer

(usa Arch Linux)

Enviado em 19/05/2008 - 17:56h

até que eu não tava TÃO ERRADO :P

infelizmente meu nivel não permite programação de kernel. quem sabe um dia..... suspiro....


12. Re: Função .(ponto) e -> (seta) em C [RESOLVIDO]

Pedro Rafael
Pedro Rafael

(usa Fedora)

Enviado em 19/05/2008 - 23:54h

Valeu aí Elgio, valeu mesmo

abraço






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts