Conversão de tipos
Esta aula aborda a conversão de tipos em C, incluindo conversão implícita, casting explícito, promoção de tipos e armadilhas comuns. O aluno aprenderá como e quando ocorrem as conversões automáticas e como controlá-las explicitamente.
A conversão de tipos em C é o processo de transformar um valor de um tipo de dado para outro. Isso pode ocorrer automaticamente (conversão implícita) ou ser forçada pelo programador (casting explícito). Compreender essas conversões é fundamental para evitar perda de dados, comportamentos inesperados e bugs sutis.
Em C, os tipos têm hierarquias e tamanhos diferentes. A conversão pode envolver tipos inteiros, ponto flutuante e ponteiros. Nesta aula, exploraremos os mecanismos de conversão, a promoção de inteiros e as armadilhas mais comuns, com exemplos práticos.
Conversão implícita
A conversão implícita (ou automática) ocorre quando o compilador converte um tipo para outro sem intervenção do programador. Isso acontece em expressões que misturam tipos diferentes, em atribuições e na passagem de argumentos para funções.
Por exemplo, ao atribuir um valor inteiro a uma variável do tipo float, o inteiro é convertido automaticamente para float:
int a = 10;
float b = a; // conversão implícita de int para float
printf("%f\n", b); // imprime 10.000000Em expressões aritméticas com operandos de tipos diferentes, o compilador realiza a conversão para um tipo comum, seguindo regras de hierarquia (por exemplo, int para float, float para double). Exemplo:
int x = 5;
double y = 2.5;
double resultado = x + y; // x é convertido para double
printf("%f\n", resultado); // 7.500000Casting explícito
O casting explícito permite que o programador force uma conversão de tipo, usando a sintaxe (tipo) expressão. Isso é útil quando se deseja evitar perda de dados ou quando a conversão implícita não é suficiente.
Por exemplo, para dividir dois inteiros e obter um resultado fracionário, é necessário converter pelo menos um operando para ponto flutuante:
int a = 7, b = 3;
float divisao = (float) a / b; // casting explícito de a para float
printf("%f\n", divisao); // 2.333333Sem o cast, a divisão seria inteira, resultando em 2. O casting explícito também é usado para converter ponteiros, mas deve ser feito com cuidado.
Promoção
Promoção de inteiros é uma conversão implícita que ocorre em expressões aritméticas e lógicas. Tipos como char e short são promovidos para int (ou unsigned int) antes da operação. Isso garante que as operações sejam realizadas com a precisão mínima do tipo int.
Exemplo:
char c1 = 'A', c2 = 'B';
int soma = c1 + c2; // c1 e c2 são promovidos a int
printf("%d\n", soma); // 131 (65 + 66)A promoção também ocorre em expressões com operadores relacionais e lógicos. É importante notar que a promoção pode causar comportamentos inesperados se o tipo promovido for unsigned, especialmente em comparações.
Armadilhas
A conversão de tipos em C apresenta várias armadilhas que podem levar a erros. Uma delas é a perda de dados ao converter de um tipo maior para um menor. Por exemplo, converter um long para int pode truncar o valor se ele exceder o intervalo do int.
Outra armadilha comum é a conversão de ponto flutuante para inteiro, que descarta a parte fracionária (truncamento). Exemplo:
double pi = 3.14159;
int parteInteira = (int) pi; // parteInteira = 3 (truncado)
printf("%d\n", parteInteira);Comparações entre tipos signed e unsigned também são problemáticas. Quando um int negativo é comparado com um unsigned int, o int é convertido para unsigned, resultando em um valor grande positivo, o que pode levar a resultados inesperados.
int a = -1;
unsigned int b = 1;
if (a < b) {
printf("-1 é menor que 1\n");
} else {
printf("-1 NÃO é menor que 1\n"); // Este é impresso!
}Nesse caso, a expressão a < b converte a para unsigned, tornando-o um número muito grande (UINT_MAX), então a comparação falha.
Boas práticas
Para evitar armadilhas, sempre use casting explícito quando a conversão não for óbvia ou quando houver risco de perda de dados. Prefira tipos consistentes em expressões e evite misturar signed e unsigned sem necessidade. Ative os avisos do compilador (flags como -Wall -Wextra) para detectar conversões suspeitas.
Referências
- cppreference.com: Conversão de tipos em C
- GNU C Manual: Type Conversions
- Microsoft C: Type Conversions
- IBM: Type conversions in C
- Tutorialspoint: C Type Casting
Exercícios
- Escreva um programa que declare um
intcom valor 257 e umchar. Atribua ointaochare imprima ambos. Explique o resultado. - Dado o código:
double d = 3.9; int i = d; printf("%d\n", i);Qual será a saída? Explique. - Escreva um programa que calcule a média de dois inteiros usando casting explícito para garantir resultado fracionário.
- O que acontece quando se compara um
intnegativo com umunsigned int? Dê um exemplo. - Explique a diferença entre promoção de inteiros e conversão implícita em atribuições.
#include <stdio.h>
int main() {
int a = 257;
char c = a;
printf("int: %d, char: %d\n", a, c);
return 0;
}O char tem apenas 8 bits, então armazena apenas os 8 bits menos significativos de 257 (que é 00000001 00000001 em binário). O valor armazenado é 1 (truncamento).#include <stdio.h>
int main() {
int a = 5, b = 2;
double media = (double) (a + b) / 2;
printf("Média: %f\n", media); // 3.500000
return 0;
}int a = -1;
unsigned int b = 1;
if (a < b) {
printf("menor\n");
} else {
printf("maior\n"); // imprime "maior"
}