Elementos de programação em C.pdf
Short Description
Download Elementos de programação em C.pdf...
Description
Elementos de programação em C Diretivas de pré-processamento
Francisco A. C. Pinheiro, Elementos de Programação em C , Bookman, 2012. Visite Visite os sítios do livro para obter material adicional: adicional: www.bookman.c www.bookman.com. om.br br e www.fac www.facp. p.pro pro.b .br/l r/livro ivroc c
Sumário
1
Diretivas de pré-processamento pré-processamento
2
Inclusão Inclusão condiciona condicionall de código
3
4
5
Macros predefinidas Erros de pré-p pré-processam rocessamento ento Bibliografia
Diretivas de pré-processamento
Inclusão de arquivos
Inclusão de arquivos
#inclu #in clude de
Inclui o arquivo arquivo do sistema sistema arqsis.
#inclu #in clude de "ar "arqusu qusu" "
Inclui o arquivo arquivo do usuário usuário arqusu.
Diretivas de pré-processamento
Inclusão de arquivos
Inclusão de arquivos
#inclu #in clude de
Inclui o arquivo arquivo do sistema sistema arqsis.
#inclu #in clude de "ar "arqusu qusu" "
Inclui o arquivo arquivo do usuário usuário arqusu.
As seguintes opções modificam a ordem de pesquisa dos diretórios na busca por arquivos durante a compilação: -Idir Coloca dir no no início da lista dos diretórios que são pesquisados na busca dos arquivos identificados pelas diretivas #include. -iquotedir Coloca dir no no início da lista dos diretórios que são pesquisados
na busca dos arquivos do usuário, se esses arquivos não estiverem no diretório corrente.
Diretivas de pré-processamento
Inclusão de arquivos
Inclusão de arquivos — ordem de pesquisa
Com as opções -I e -iquote, a seguinte ordem de pesquisa é adotada: Os arquivos do sistema são pesquisados primeiro nos diretórios especificados pelas opções -I, e por último nos diretórios padrões do sistema. Os arquivos do usuário são pesquisados primeiro no diretório corrente, a seguir nos diretórios especificados pelas opções iquote, depois nos diretórios especificados pelas opções -I, e por último nos diretórios padrões do sistema.
Diretivas de pré-processamento Macros
Definindo constantes #define nome_macro expressão_definidora
Durante o pré-processamento todas as referências a macros são substituídas por sua definição. A expressão definidora de uma macro não é avaliada no processo de substituição, que é puramente textual. A expressão resultante da substituição é avaliada durante a compilação. As macros podem ser usadas na definição de outras macros: Após cada substituição o texto resultante é reanalisado e, se nele houver macros, novas substituições têm efeito. Entretanto, se em algum momento o texto resultante contém o nome da macro sendo substituída, esse nome não é mais objeto de avaliação.
Diretivas de pré-processamento Macros
Definindo constantes Exemplo
A sequência de definições ao lado faz com que VF seja substituída por:
# d ef in e # d e fi ne # d ef in e # d e f in e # d e fi ne # d ef in e # d ef in e
VP 50 0 A NO S 1 3 M ES ES 1 J U R OS _ PE R C 0 .6 J UR OS J UR O S_ PE R C / 1 00 P ER IO DO A NO S * 12 + M ES ES VF VP * po w ((1 + J UR OS ) , P ER IO DO )
500 * pow((1 + 0.6 / 100), 13 * 12 + 1)
Diretivas de pré-processamento Macros
Definindo constantes Exemplo
A sequência de definições ao lado faz com que VF seja substituída por:
# d ef in e # d e fi ne # d ef in e # d e f in e # d e fi ne # d ef in e # d ef in e
VP 50 0 A NO S 1 3 M ES ES 1 J U R OS _ PE R C 0 .6 J UR OS J UR O S_ PE R C / 1 00 P ER IO DO A NO S * 12 + M ES ES VF VP * po w ((1 + J UR OS ) , P ER IO DO )
500 * pow((1 + 0.6 / 100), 13 * 12 + 1)
VF
→
VP * pow((1 + JUROS), PERIODO)
Diretivas de pré-processamento Macros
Definindo constantes Exemplo
A sequência de definições ao lado faz com que VF seja substituída por:
# d ef in e # d e fi ne # d ef in e # d e f in e # d e fi ne # d ef in e # d ef in e
VP 50 0 A NO S 1 3 M ES ES 1 J U R OS _ PE R C 0 .6 J UR OS J UR O S_ PE R C / 1 00 P ER IO DO A NO S * 12 + M ES ES VF VP * po w ((1 + J UR OS ) , P ER IO DO )
500 * pow((1 + 0.6 / 100), 13 * 12 + 1)
VF
→ →
VP * pow((1 + JUROS), PERIODO) 500 * pow((1 + JUROS), PERIODO)
Diretivas de pré-processamento Macros
Definindo constantes Exemplo
A sequência de definições ao lado faz com que VF seja substituída por:
# d ef in e # d e fi ne # d ef in e # d e f in e # d e fi ne # d ef in e # d ef in e
VP 50 0 A NO S 1 3 M ES ES 1 J U R OS _ PE R C 0 .6 J UR OS J UR O S_ PE R C / 1 00 P ER IO DO A NO S * 12 + M ES ES VF VP * po w ((1 + J UR OS ) , P ER IO DO )
500 * pow((1 + 0.6 / 100), 13 * 12 + 1)
VF
→ → →
VP * pow((1 + JUROS), PERIODO) 500 * pow((1 + JUROS), PERIODO) 500 * pow((1 + JUROS_PERC / 100), PERIODO)
Diretivas de pré-processamento Macros
Definindo constantes Exemplo
A sequência de definições ao lado faz com que VF seja substituída por:
# d ef in e # d e fi ne # d ef in e # d e f in e # d e fi ne # d ef in e # d ef in e
VP 50 0 A NO S 1 3 M ES ES 1 J U R OS _ PE R C 0 .6 J UR OS J UR O S_ PE R C / 1 00 P ER IO DO A NO S * 12 + M ES ES VF VP * po w ((1 + J UR OS ) , P ER IO DO )
500 * pow((1 + 0.6 / 100), 13 * 12 + 1)
VF
→ → →
VP * pow((1 + JUROS), PERIODO) 500 * pow((1 + JUROS), PERIODO) 500 * pow((1 + JUROS_PERC / 100), PERIODO) e assim por diante.
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções
#define nome_macro (lista_parâmetros ) expressão_definidora
A lista de parâmetros deve vir imediatamente após o nome da macro, sem espaço entre eles. Os parâmetros são especificados entre parênteses, separados por vírgula. Os parâmetros de uma macro podem não ser usados na expressão definidora. As referências a uma macro parametrizada devem respeitar o número de parâmetros de sua definição.
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções #define f(x) 2 * (x)
#define abs(val, x) if ((x) < 0) (val) = -(x); else (val) = (x)
#define g(a, x y )(a)
>
0?(a) : (x y)
#define fun(a, b, c) 2 * (a) + (b)
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções #define f(x) 2 * (x) f(x + 3) → 2 * (x + 3) #define abs(val, x) if ((x) < 0) (val) = -(x); else (val) = (x)
#define g(a, x y )(a)
>
0?(a) : (x y)
#define fun(a, b, c) 2 * (a) + (b)
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções #define f(x) 2 * (x) f(x + 3) → 2 * (x + 3) #define abs(val, x) if ((x) < 0) (val) = -(x); else (val) = (x) abs(&num, -2) → if ((-2) < 0) (&num) = -(-2); else (&num) = (-2) #define g(a, x y )(a)
>
0?(a) : (x y)
#define fun(a, b, c) 2 * (a) + (b)
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções #define f(x) 2 * (x) f(x + 3) → 2 * (x + 3) #define abs(val, x) if ((x) < 0) (val) = -(x); else (val) = (x) abs(&num, -2) → if ((-2) < 0) (&num) = -(-2); else (&num) = (-2) #define g(a, x y )(a)
>
0?(a) : (x y)
g(x + y, 21) → (x + y) > 0 ?
(x + y) :
#define fun(a, b, c) 2 * (a) + (b)
(21).
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções #define f(x) 2 * (x) f(x + 3) → 2 * (x + 3) #define abs(val, x) if ((x) < 0) (val) = -(x); else (val) = (x) abs(&num, -2) → if ((-2) < 0) (&num) = -(-2); else (&num) = (-2) #define g(a, x y )(a)
>
0?(a) : (x y)
g(x + y, 21) → (x + y) > 0 ?
(x + y) :
#define fun(a, b, c) 2 * (a) + (b) fun(2 * c, c, y) → 2 * ( 2 + c ) + ( c ).
(21).
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções — argumentos variáveis
Os parâmetros variáveis são identificados por reticências na lista de parâmetros. Na referência, os argumentos que correspondem aos parâmetros variáveis (incluindo as vírgulas que os separam) são tratados como um único valor, substituindo o identificador __VA_ARGS__.
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções — argumentos variáveis
Exemplo A macro #define soma(x, ...)
x + adiciona(__VA_ARGS__)
resulta nas seguintes substituições: soma(2, 3) soma(a, b, c) soma(6, 4, x + 3, c)
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções — argumentos variáveis
Exemplo A macro #define soma(x, ...)
x + adiciona(__VA_ARGS__)
resulta nas seguintes substituições: soma(2, 3) soma(a, b, c) soma(6, 4, x + 3, c)
→
2 + adiciona(3)
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções — argumentos variáveis
Exemplo A macro #define soma(x, ...)
x + adiciona(__VA_ARGS__)
resulta nas seguintes substituições: soma(2, 3) soma(a, b, c) soma(6, 4, x + 3, c)
→ →
2 + adiciona(3) a + adiciona(b, c)
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções — argumentos variáveis
Exemplo A macro #define soma(x, ...)
x + adiciona(__VA_ARGS__)
resulta nas seguintes substituições: soma(2, 3) soma(a, b, c) soma(6, 4, x + 3, c)
→ → →
2 + adiciona(3) a + adiciona(b, c) 6 + adiciona(4, x + 3, c)
Diretivas de pré-processamento
Macros parametrizadas
Representando argumentos como cadeias de caracteres
O símbolo # é tratado como um operador de substituição literal, quando antecede o identificador de um parâmetro na definição de uma macro. Seu efeito é delimitar com aspas a expressão usada como argumento na referência à macro: a expressão arg é transformada em "arg ".
Diretivas de pré-processamento
Macros parametrizadas
Representando argumentos como cadeias de caracteres
Exemplo A macro #define imprime(x) printf("arg " #x " = %d\n", (x))
resulta nas seguintes substituições: imprime(x) imprime(4 + a)
Diretivas de pré-processamento
Macros parametrizadas
Representando argumentos como cadeias de caracteres
Exemplo A macro #define imprime(x) printf("arg " #x " = %d\n", (x))
resulta nas seguintes substituições: imprime(x) imprime(4 + a)
−→
printf("arg ""x"" = %d\n", (x))
Diretivas de pré-processamento
Macros parametrizadas
Representando argumentos como cadeias de caracteres
Exemplo A macro #define imprime(x) printf("arg " #x " = %d\n", (x))
resulta nas seguintes substituições: imprime(x) imprime(4 + a)
−→ −→
printf("arg ""x"" = %d\n", (x)) printf("arg x = %d\n", (x))
Diretivas de pré-processamento
Macros parametrizadas
Representando argumentos como cadeias de caracteres
Exemplo A macro #define imprime(x) printf("arg " #x " = %d\n", (x))
resulta nas seguintes substituições: imprime(x)
−→ −→
printf("arg ""x"" = %d\n", (x)) printf("arg x = %d\n", (x))
imprime(4 + a)
−→
printf("arg ""4 + a"" = %d\n", (4 + a))
Diretivas de pré-processamento
Macros parametrizadas
Representando argumentos como cadeias de caracteres
Exemplo A macro #define imprime(x) printf("arg " #x " = %d\n", (x))
resulta nas seguintes substituições: imprime(x)
−→ −→
printf("arg ""x"" = %d\n", (x)) printf("arg x = %d\n", (x))
imprime(4 + a)
−→ −→
printf("arg ""4 + a"" = %d\n", (4 + a)) printf("arg 4 + a = %d\n", (4 + a))
Diretivas de pré-processamento
Macros parametrizadas
Concatenando argumentos
O operador ## na definição de uma macro causa a concatenação do termo que o precede com o termo que o segue imediatamente: a expressão a ## b produz ab.
Diretivas de pré-processamento
Macros parametrizadas
Concatenando argumentos Exemplo As macros #define arg(x, y, z, w) int val ## x ## y ## z = w #define imp(x,y,z) printf("val" #x #y #z " = %d\n", val ## x ## y ## z)
produzem as seguintes substituições: arg(1, 2, 3, 869); arg(1,2, ,869); arg( , , ,869); imp(1, 2, 3); imp(1,2,); imp( , , );
Diretivas de pré-processamento
Macros parametrizadas
Concatenando argumentos Exemplo As macros #define arg(x, y, z, w) int val ## x ## y ## z = w #define imp(x,y,z) printf("val" #x #y #z " = %d\n", val ## x ## y ## z)
produzem as seguintes substituições: arg(1, 2, 3, 869); arg(1,2, ,869); arg( , , ,869); imp(1, 2, 3); imp(1,2,); imp( , , );
→
int val123 = 869;
Diretivas de pré-processamento
Macros parametrizadas
Concatenando argumentos Exemplo As macros #define arg(x, y, z, w) int val ## x ## y ## z = w #define imp(x,y,z) printf("val" #x #y #z " = %d\n", val ## x ## y ## z)
produzem as seguintes substituições: arg(1, 2, 3, 869); arg(1,2, ,869); arg( , , ,869); imp(1, 2, 3); imp(1,2,); imp( , , );
→ →
int val123 = 869; int val12 = 869;
Diretivas de pré-processamento
Macros parametrizadas
Concatenando argumentos Exemplo As macros #define arg(x, y, z, w) int val ## x ## y ## z = w #define imp(x,y,z) printf("val" #x #y #z " = %d\n", val ## x ## y ## z)
produzem as seguintes substituições: arg(1, 2, 3, 869); arg(1,2, ,869); arg( , , ,869); imp(1, 2, 3); imp(1,2,); imp( , , );
→ → →
int val123 = 869; int val12 = 869; int val = 869;
Diretivas de pré-processamento
Macros parametrizadas
Concatenando argumentos Exemplo As macros #define arg(x, y, z, w) int val ## x ## y ## z = w #define imp(x,y,z) printf("val" #x #y #z " = %d\n", val ## x ## y ## z)
produzem as seguintes substituições: arg(1, 2, 3, 869); arg(1,2, ,869); arg( , , ,869);
→ → →
int val123 = 869; int val12 = 869; int val = 869;
imp(1, 2, 3); imp(1,2,); imp( , , );
→
printf("val123 = %d\n", val123);
Diretivas de pré-processamento
Macros parametrizadas
Concatenando argumentos Exemplo As macros #define arg(x, y, z, w) int val ## x ## y ## z = w #define imp(x,y,z) printf("val" #x #y #z " = %d\n", val ## x ## y ## z)
produzem as seguintes substituições: arg(1, 2, 3, 869); arg(1,2, ,869); arg( , , ,869);
→ → →
int val123 = 869; int val12 = 869; int val = 869;
imp(1, 2, 3); imp(1,2,); imp( , , );
→ →
printf("val123 = %d\n", val123); printf("val12 = %d\n", val12);
Diretivas de pré-processamento
Macros parametrizadas
Concatenando argumentos Exemplo As macros #define arg(x, y, z, w) int val ## x ## y ## z = w #define imp(x,y,z) printf("val" #x #y #z " = %d\n", val ## x ## y ## z)
produzem as seguintes substituições: arg(1, 2, 3, 869); arg(1,2, ,869); arg( , , ,869);
→ → →
int val123 = 869; int val12 = 869; int val = 869;
imp(1, 2, 3); imp(1,2,); imp( , , );
→ → →
printf("val123 = %d\n", val123); printf("val12 = %d\n", val12); printf("val = %d\n", val);
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções — recomendações
Os parâmetros devem ser delimitados por parênteses #define mult(x, y) (x) * (y)
é preferível a #define mult(x, y) x * y
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções — recomendações
Os parâmetros devem ser delimitados por parênteses #define mult(x, y) (x) * (y) mult(x + 3, x + 3) → ( x + 3 ) * ( x + 3 )
é preferível a #define mult(x, y) x * y mult(x + 3, x + 3) → x + 3 * x + 3
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções — recomendações
Deve-se evitar argumentos com efeitos colaterais #define dobro(x) (x) + (x)
é diferente de int dobro(int x) {return x + x;}
Diretivas de pré-processamento
Macros parametrizadas
Simulando funções — recomendações
Deve-se evitar argumentos com efeitos colaterais #define dobro(x) (x) + (x) x = 4; y = dobro(++x);
resulta em
x = 6 y = 12
é diferente de int dobro(int x) {return x + x;} x = 4; y = dobro(++x);
resulta em
x = 5 y = 10
Diretivas de pré-processamento
Tornando definições sem efeito
Tornando definições sem efeito
#define LINUX define a macro LINUX #undef WINDOWS torna sem efeito a definição da macro LINUX
Em tempo de compilação pode-se usar as opções -D e -U para definir e tornar as definições sem efeito: gcc -o prog prog.c -std=c99 -DLINUX -UWINDOWS
Diretivas de pré-processamento
Testando a definição de macros
Testando a definição de macros
Operador defined A expressão defined NOME ou defined(NOME) resulta no valor 1 (verdadeiro), se a macro NOME está definida, ou no valor 0 (falso), em caso contrário.
Operador !defined A expressão !defined NOME ou !defined(NOME) resulta no valor 1 (verdadeiro), se a macro NOME não está definida, ou no valor 0 (falso), em caso contrário.
Inclusão condicional de código
Inclusão condicional de código O comando #if e suas variações são usados para inclusão condicional de código:
# if d ef in ed L IN UX #endif
# i f ! d e fi ne d L IN UX #else #endif
# i f ! d e fi ne d L IN UX #else # if d ef in ed M AC #endif #endif
Inclusão condicional de código
Inclusão condicional de código #ifdef #ifndef #elif #endif #endelif
é abreviação de é abreviação de é abreviação de termina os comandos termina o comando
# i f d ef U NI X # e l if d e fi n ed W I ND O WS #endelif #endif
#if defined #if !defined #else #if #if e #elif #elif
# i f d ef U NI X # e l if d e fi n ed W I ND O WS #endif
# i f n de f S UN # e li f d ef in ed PC # e li f d ef in ed M AC #endif
Inclusão condicional de código
Avaliação da condição
Avaliação da condição
1
2
Os identificadores que são nomes de macros definidas, e não são operandos do operador defined, são substituídos por suas definições. As operações defined são avaliadas, resultando no valor 1, se a macro usada como operando está definida, ou no valor 0, em caso contrário.
3 4
Os identificadores remanescentes são substituídos por 0. A expressão resultante é avaliada. A expressão resultante deve ser uma expressão inteira constante, mas não pode conter o operador sizeof nem o operador de conversão de tipo.
Inclusão condicional de código
Avaliação da condição
Avaliação da condição Exemplo Para as macros ao lado, a tabela a seguir mostra como a condição da diretiva #if é avaliada.
# d e fi ne E 1 # u n de f E 2 # d ef in e E2 12 # d e fi ne E 3 # u n de f E 3 # d e fi ne E 5 L IN UX # define SUNOS 1
Antes
Após subst.
Aval
#if #if #if #if #if
#if #if #if #if #if
#if #if #if #if #if
defined E1 !defined E2 !defined E3 E2 == 3 * (2
View more...
Comments