.. | ||
dump.c | ||
limites.c | ||
quadrado-long.c | ||
quadrado.c | ||
README.org |
Curso Básico da Linguagem C
- Aula 3: Tipos de dados
Aula 3: Tipos de dados
Exemplo da última aula (quadrado.c
)
#include <stdio.h>
int quadrado(int base) {
return base * base;
}
int main(void) {
int num = 100000;
printf("%d^2 = %d\n", num, quadrado(num));
return 0;
}
O que há de novo:
int num = 100000;
→ A base será 100.000
Compilando e executando…
:~$ gcc quadrado.c :~$ ./a.out 100000^2 = 1410065408
O resultado está obviamente errado!
Tipos são tamanhos de dados na memória
- Bit: algarismos 0 ou 1;
- Byte: 8 bits;
- Tipo
int
: 32 bits == 4 bytes (arquitetura x86_64).
Maior número que se pode escrever com 4 bytes (32bits):
(2^32) - 1 = 4.294.967.295
Quadrado de 100.000:
100.000^2 = 10.000.000.000
O que aconteceu?
Bytes necessários para escrever 10.000.000.000:
:~$ printf '0x%016x\n' 10000000000 0x00000002540be400 ↑ 5 bytes
Bytes truncados pelo limite do tipo int
(4 bytes):
:~$ printf '0x%016x\n' 1410065408 0x00000000540be400 ↑ 4 bytes
Precisamos de mais espaço para escrever o resultado:
Tipo | Tamanho | Faixa de valores |
---|---|---|
char |
1 byte | -128 a 127 |
short |
2 bytes | -32.768 a 32.767 |
int |
4 bytes | -2.147.483.648 a 2.147.483.647 |
long |
8 bytes | -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807 |
Todos esses tipos consideram o uso de valores com sinal!
Exemplo corrigido (quadrado-long.c
)
#include <stdio.h>
unsigned long quadrado(long base) {
return base * base; /* Qual é o tipo dessa expressão? */
}
int main(void) {
long num = 100000;
printf("%ld^2 = %lu\n", num, quadrado(num));
return 0;
}
## Compilando e executando…
:~$ gcc quadrado-long.c :~$ ./a.out 100000^2 = 10000000000
Tipos primitivos
Tipo | Tamanho | Faixa de valores (x86_64) |
---|---|---|
char |
1 byte | -128 a 127 |
short |
2 bytes | -32.768 a 32.767 |
int |
4 bytes | -2.147.483.648 a 2.147.483.647 |
float |
4 bytes | 1,18E-38 a 3,40E+38 |
double |
8 bytes | 2,23E-308 a 1,80E+308 |
Qualificador unsigned
(sem sinal):
Tipo | Tamanho | Faixa de valores (x86_64) |
---|---|---|
unsigned char |
1 byte | 0 a 255 |
unsigned short |
2 bytes | 0 a 65.535 |
unsigned int |
4 bytes | 0 a 4.294.967.295 |
Qualificador long
:
Tipo | Tamanho | Faixa de valores (x86_64) |
---|---|---|
long |
8 bytes | -9223372036854775808 a 9223372036854775807 |
unsigned long |
8 bytes | 0 a 18446744073709551615 |
long double |
16 bytes | 3,36E-4932 a 1,19E+4932 |
Tipos customizados
Nós podemos criar apelidos para tipos:
typedef [QUALIFICADORES] TIPO NOME;
Exemplos:
typedef int i32;
typedef unsigned int u32;
typedef long int i64;
typedef unsigned long int u64;
Para diferenciar de nomes de variáveis, é comum utilizar o sufixo _t
(de type):
typedef int i32_t;
typedef unsigned int u32_t;
typedef long int i64_t;
typedef unsigned long int u64_t;
Expressões constantes (valores literais)
EXPRESSÃO | TIPO |
---|---|
42 |
int |
42U |
unsigned int |
42L |
long int |
42UL |
unsigned long int |
42LL |
long long int |
42ULL |
unsigned long long int |
'a' |
int |
12.3 |
double |
1e16 |
double |
12.3F |
float |
1e16F |
float |
12.3L |
long double |
1e16L |
long double |
"salve" |
unsigned long (endereço) |
O tipo void
No contexto de declarações de funções, void
representa a ausência de tipo,
mas pode ter outros significados.
Funções sem valor de retorno:
void func(int num) {
printf("num x 2 = %d\n", num * 2);
}
Retorno não é o que a função imprime, mas o valor que ela expressa!
Funções que não recebem argumentos:
int func(void) {
puts("Nada a fazer...");
return 42;
}
Ponteiros de dados de tipo indeterminado:
void *ptr;
Ponteiros são variáveis que recebem endereços da memória (aula 5).
Modelagem de tipos (type casting)
Type casting é a conversão explícita de um tipo de dado para outro, utilizando
a sintaxe (TIPO)
antes de um valor ou de uma variável:
Exemplo:
(double)5 /* O inteiro '5' será compilado como 'double'. */