• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

mellony

Bibliotecas em C

16 mensagens neste tópico

Boas

Queria saber se é possivel construir uma biblioteca? tipo criar um ficheiro por exemplo teste.h e depois quando estivesse a fazer o programa, colocaria lá o <teste.h> e assim simplificaria o codigo, pois eu quero reservar certas palavras para terem um significado, e queria então criar uma outra biblioteca..isto é possivel?

Cumps

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Então o que é que eu teria que escrever no ficheiro teste.h para que num programa que tivesse invocada essa biblioteca, sempre que eu escreve-se "algarve", fosse o mesmo que escrever n=2?

E onde é que colocaria o ficheiro? na mesma pasta que o programa?

E depois quando já tivesse o executavel, ainda iria precisar desse ficheiro de biblioteca? e se sim onde é que o colocaria?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Então o que é que eu teria que escrever no ficheiro teste.h para que num programa que tivesse invocada essa biblioteca, sempre que eu escreve-se "algarve", fosse o mesmo que escrever n=2?

Ui! Estás a ir por caminhos perigosos. Macros? Só se absolutamente necessário.

Continua a ler o livro que a tua mãe te comprou mellony.

Pôxa... não percebo qual é a dificuldade em aprenderes por etapas.

Até tens um livro! Não é dos melhores, certo. Mas é um livro. Lê o livro!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu não sei ao certo qual a aplicação do que perguntaste... Mas tenho quase a certeza que tens outras formas bem mais simples de fazer o que pretendes.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Continua a ler o livro que a tua mãe te comprou mellony.

:cheesygrin:

Ui! Estás a ir por caminhos perigosos. Macros? Só se absolutamente necessário.

Dá-se o nome de Macros, se eu quiser que determinada palavras representem um determinado codigo fonte?

Isso dáva-me jeito.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ui! Estás a ir por caminhos perigosos. Macros? Só se absolutamente necessário.

Perigoso? Porquê? Que eu saiba uma macro é trabalho do pré-processador, não vejo a que propósito é perigoso...  :hmm:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

http://www.brainbell.com/tutors/c/Advice_and_Warnings_for_C/Macros_and_Miscellaneous_Pitfalls.html

Claro está que depois as tuas macros vão ser cada vez mais complicadas e cada vez mais difíceis de perceber algumas vezes mesmo minutos depois de as teres criado, o que complicará qualquer alteração que queiras fazer ao código. Pior, uma vez que quem opera nas macros é o preprocessador, não terás muitas hipóteses de fazer debug ao teu código quando as tuas macros contiverem erros (e elas vão conter erros). Estás sozinho e sem ferramentas de debug. Boa sorte.

Ainda, a macro retira expressividade ao código (em vez de lhe dar como se gosta de pensar). O expressividade do C está na sua syntax e semântica e as macros metem-se pelo caminho retirado a um programador que esteja a observar o teu código a capacidade de o entender sem ter que andar à procura se faz_isto(x, y) é uma função ou uma macro e onde é que está a sua definição. Se for uma macro ele ainda por cima terá que interpretar o código da macro. Uma tarefa que até mesmo para programadores experientes com muitos anos de C, é muitas vezes difícil. Resumindo, as macros tornam o código mais difícil de ler e entender.

Macros, a serem criadas devem sê-lo por razões muito específicas.

Escrever #define double( x ) ( 2 * ( x ) ) é para todos os efeitos um absurdo. Para quê complicar o que não poderia ser mais simples do que multiplicar um valor por 2? Mas acredites ou não, exemplos como este não faltam em código real.

Por outro lado temos as macros mais complicadas, essas sim com o objectivo de simplificar o código... mas então temos os problemas que falei acima. Falta de capacidade do debugger em ajudar a depurar uma macro, dificuldade em entender o código associado à macro, e dificuldade em perceber o que o código está a fazer, porque essa informação está escondida por detrás de uma macro.

...

Macros não são bichos que não se devem utilizar. São antes bichos que se devem evitar. Se existe uma boa razão para criar e usar uma macro, pois bem. Como disse existem mesmo inteiras áreas da programação que dificilmente poderão ser aplicadas sem a utilização de Macros. Mas para a maioria dos casos a macro pode e deve ser ignorada em favor de um código mais estruturado, legível e acima de tudo, fácil de manter.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Marfig, bom post, fiquei com melhor noção das macros, e das consequencias de não poder ver se há erros.

Mas mesmo assim como se usa uma macro em C, da mais simples maneira?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O expressividade do C está na sua syntax e semântica e as macros metem-se pelo caminho retirado a um programador que esteja a observar o teu código a capacidade de o entender sem ter que andar à procura se faz_isto(x, y) é uma função ou uma macro e onde é que está a sua definição. Se for uma macro ele ainda por cima terá que interpretar o código da macro. Uma tarefa que até mesmo para programadores experientes com muitos anos de C, é muitas vezes difícil. Resumindo, as macros tornam o código mais difícil de ler e entender.

Só se as usares mal. Existe a prática que as macros devem ter um nome composto apenas por maiusculas, isto diferencia uma macro duma função.

Eu acho que o teu texto se pode simplificar dizendo que as macros devem ser usadas para coisas simples, tipicamente 1 linha de código, para coisas mais complexas, devem-se usar funções. Ao usar macros para coisas simples em relação a funções tem-se a vantagem da poupança do tempo de chamada da função por exemplo.

Escrever #define double( x ) ( 2 * ( x ) ) é para todos os efeitos um absurdo. Para quê complicar o que não poderia ser mais simples do que multiplicar um valor por 2? Mas acredites ou não, exemplos como este não faltam em código real.

Este exemplo é muito mau. Neste caso é óbvio que não compensa.

Agora usar uma macro para um ciclo "for"

#define FOR(i,n)      for( i = 0 ; i < (n) ; i++ )

Reduz o tamanho do código, mas de facto dificulta bastante a legibilidade.

Por outro lado, eu considero que as macros são muito úteis para operações bit-a-bit.

#define TWO(n)                  ( 1 << (n) )
#define CONTAINS( Set, i ) 	( ( (Set) & TWO(i) ) !=0 )

Assim para saber se "mask" tem o bit "i" a 1 posso fazer

if ( CONTAINS( mask , i ) )

// em vez de

if ( (mask & (1<<i) ) != 0)  // que considero menos legivel

Além disso estas macros são facilmente reutilizáveis noutros programas.

Mas eu costumo usar macros para constantes, exemplos:

#define MAX   1000
#define GREEN 0x3A5F
#define BLUE  0xE157
#define NORTH 1
#define SOUTH 2

Mas estas podiam ser variaveis constantes sem problema.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Mas eu costumo usar macros para constantes, exemplos:

Usar macros para constantes não faz sentido, ocupa mais storage no programa, não são type-safe, e não tens informação simbólica em modo de debug. Usem tipos constantes. :thumbsup:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

São estilos mogers. Seria difícil para mim dizer que não o deves fazer. É a tua preferência.

Pessoalmente evito todo e qualquer uso de macros. Apenas uso macros quando quero que o pre-processador entre em acção. Foi para isso que foram criadas, não para alterar a expressividade do meu código. Infelizmente o seu uso é muito vezes isso mesmo: fazer do C (ou do C++ para todos os efeitos) parecer algo que não é.

Concordamos em parte. Mas mesmo no teu último exemplo (o checkbit) eu recusar-me-ia a usar uma macro para controlar a legibilidade do meu código. Podes perfeitamente colocar esse código numa função e esqueceres o assunto. Mais legível que if ( CONTAINS( mask , i ) ) não é certamente if ( contains(mask, i) ). São ambas a mesma coisa, mas no último caso mantens a expressividade da linguagem e a função contains() é mais fácil de manter, alterar e adicionar código se assim o desejares, do que a macro que lhe está associada.

No caso das constantes, exactamente como o Triton disse. Mas percebi perfeitamente que sabes disso. De notar no entanto que quando me refiro a macros, estou essencialmente a referir-me ao Code Substitution que muitas vezes lhe está associado como nos exemplos restantes. A presença de #define para controlar o compilador é uma outra área comum para a utilização de macros, e uma contra a qual não tenho nada. Antes pelo contrário.

EDIT: Já agora uma curiosidade um pouco OT... Aquela coisa do USACO (não conhecia isto até à uns dias atrás) penaliza o uso de macros?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Como referi no outro post, o facto de evitar o uso de uma função para uma coisa tão simples tem vantagens. Se se optar por não usar nem macro nem função pode-nos acontecer como a um concorrente na final do TopCoder Open 2007 que se esqueceu de uns () num shift e perdeu 24000$ :thumbsup:

No USACO ou em qualquer judge online ou de competições que conheço não há penalizações desse género. A única coisa que conta é o que o executável produz após compilar o nosso código sem erros ou warnings. A única excepção é o TopCoder que penaliza o uso excessivo de código não usado (porque existe uma fase das competições onde podemos tentar encontrar bugs no código de outros concorrentes e ganhar pontos).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu tenho um trauma com as macros por causa de uma discussão que tive com uma colega de grupo, porque ela dizia que queria pôr os nomes das macros em maiúsculas, e eu dizia que isso ficava feio........

A minha regra costumava ser:

1 - Para aquelas macros que servem só para evitar o "calling overhead" das funções, usar as mesmas convenções que se usa para as funções. Por exemplo, para uma implementação de linked lists, podes usar a macro listsethead() para substituir uma função com o mesmo nome. Estas macros só fazem coisas que seria possível fazer com funções (por exemplo, não têm argumentos "de saida").

2 - Para aquelas macros que fazem coisas inesperadas, usar nomes em maiusculas. Por exemplo, uma macro que simule templates, para declarar funções idênticas que trabalhem sobre vários tipos de números. Outro exemplo: uma macro com argumentos de saida.

A aproximação ideal é não usar macros que se encaixam na categoria 1 durante a fase de desenvolvimento. Isto, porque as macros são só artifícios de optimização. Como já não estamos na era das linguagens de segunda geração, esses detalhes devem estar ausentes durante a fase de desenvolvimento.

Por exemplo, podes inicialmente usar só funções. Mais tarde, quando fores lançar o programa, #ifdefas as funções o os respectivos protótipos, crias as macros, e usas mais #ifdefs (mas desta vez ao contrário) para as novas macros.

Como isto é pouco prático e torna os programas mais difíceis de perceber, o meu conselho é esquecer as macros. Quem usa compiladores que suportem C99 (p.ex. o gcc), deve usar funções inline, que só são integradas nos locais de chamamento se pedirmos para optimizar, e se o compilador achar que isso é boa ideia. Quando as funções forem privadas a um só módulo, deve utilizar-se *mesmo* o static.

Adicionalmente, pode definir-se a função num header, como static inline. Se lhe meteres o atributo "always-inline", o resultado vai ser exactamente igual a uma macro.

Há mais coisas que se podem dizer sobre a optimização e o inlining. Por exemplo, se passarmos todos os ficheiros .c ao gcc ao mesmo tempo, e incluirmos as opções -combine, -fwhole-program e -O3, ele integra-te quase tudo. Alguns dos programas (meus) em que eu testei isso, ele integrou *tudo* (i.e. ficou tudo reduzido a uma única main() ). Pareceu-me exagero, mas se calhar foi mesmo a melhor alternativa.

Em geral, a menos que haja um loop a "cruzar" a margem da cache, é sempre melhor integrar. A única excepção é se quisermos fazer dynamic linking ou se alguma função não for recursiva final. Por outro lado, expôr esse tipo de detalhes não faz qualquer sentido para nenhuma linguagem que não seja ASM.

Queria saber se é possivel construir uma biblioteca? tipo criar um ficheiro por exemplo teste.h e depois quando estivesse a fazer o programa, colocaria lá o <teste.h> e assim simplificaria o codigo, pois eu quero reservar certas palavras para terem um significado, e queria então criar uma outra biblioteca..isto é possivel?

Preocupa-te primeiro em aprender bem a linguagem.

JJ

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora