diff --git a/README.org b/README.org index 6d31dcd..b7b1d06 100644 --- a/README.org +++ b/README.org @@ -15,10 +15,11 @@ qualquer distribuição. - [[./aulas][Exemplos utilizados nas aulas]]. - [[./c17/iso-iec-9899-2017.pdf][Especificações C17]] (PDF em inglês). - [[./c23/iso-iec-9899-2024.pdf][Especificações C23]] (PDF em inglês). +- [[https://fiorix.wordpress.com/wp-content/uploads/2014/04/o-fantc3a1stico-mundo-da-linguagem-c.pdf][O Fantástico Mundo da Linguagem C - Alexandre Firori]] (PDF). ** Anotações e vídeos - 10.03.2025 [[./aulas/00-intro/README.org][Aula 0: Sobre o curso]] ([[https://youtu.be/RZmfuuABTHY][vídeo]]) - 12.03.2025 [[./aulas/01-historia/README.org][Aula 1: História]] ([[https://youtu.be/wqJQL5W9FIw][vídeo]]) ([[./exercicios/01/README.org][exercícios]]) - 14.03.2025 [[./aulas/02-dados-e-instrucoes/README.org][Aula 2: Dados e instruções]] ([[https://youtu.be/2KsvRJjshQ0][vídeo]]) ([[./exercicios/02/README.org][exercícios]]) - +- 17.03.2025 [[./aulas/03-tipos-de-dados/README.org][Aula 3: Tipos de dados]] ([[https://youtu.be/iMiRzZCU7hE][vídeo]]) ([[./exercicios/03/README.org][exercícios]]) diff --git a/aulas/03-tipos-de-dados/README.org b/aulas/03-tipos-de-dados/README.org new file mode 100644 index 0000000..dd57072 --- /dev/null +++ b/aulas/03-tipos-de-dados/README.org @@ -0,0 +1,235 @@ +#+title: Curso Básico da Linguagem C +#+subtitle: Aula 3: Tipos de dados +#+author: Blau Araujo +#+startup: show2levels +#+options: toc:3 + +* Aula 3: Tipos de dados + +- [[https://youtu.be/iMiRzZCU7hE][Vídeo desta aula]] +- [[https://fiorix.wordpress.com/wp-content/uploads/2014/04/o-fantc3a1stico-mundo-da-linguagem-c.pdf][O Fantástico Mundo da Linguagem C - Alexandre Firori]] + +** Exemplo da última aula (=quadrado.c=) + +#+begin_src c +#include + +int quadrado(int base) { + return base * base; +} + +int main(void) { + int num = 100000; + + printf("%d^2 = %d\n", num, quadrado(num)); + return 0; +} +#+end_src + +O que há de novo: + +~int num = 100000;~ → A base será 100.000 + +Compilando e executando... + +#+begin_example +:~$ gcc quadrado.c +:~$ ./a.out +100000^2 = 1410065408 +#+end_example + +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): + +#+begin_example +(2^32) - 1 = 4.294.967.295 +#+end_example + +Quadrado de 100.000: + +#+begin_example +100.000^2 = 10.000.000.000 +#+end_example + +*** O que aconteceu? + +Bytes necessários para escrever 10.000.000.000: + +#+begin_example +:~$ printf '0x%016x\n' 10000000000 +0x00000002540be400 + ↑ + 5 bytes +#+end_example + +Bytes truncados pelo limite do tipo =int= (4 bytes): + +#+begin_example +:~$ printf '0x%016x\n' 1410065408 +0x00000000540be400 + ↑ + 4 bytes +#+end_example + +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=) + +#+begin_src c +#include + +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; +} +#+end_src + +## Compilando e executando... + +#+begin_example +:~$ gcc quadrado-long.c +:~$ ./a.out +100000^2 = 10000000000 +#+end_example + +** 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: + +#+begin_example +typedef [QUALIFICADORES] TIPO NOME; +#+end_example + +*** Exemplos: + +#+begin_src c +typedef int i32; +typedef unsigned int u32; +typedef long int i64; +typedef unsigned long int u64; +#+end_src + +Para diferenciar de nomes de variáveis, é comum utilizar o sufixo =_t= (de /type/): + +#+begin_src c +typedef int i32_t; +typedef unsigned int u32_t; +typedef long int i64_t; +typedef unsigned long int u64_t; +#+end_src + +** 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: + +#+begin_src c +void func(int num) { + printf("num x 2 = %d\n", num * 2); +} +#+end_src + +#+begin_quote +Retorno não é o que a função imprime, mas o valor que ela expressa! +#+end_quote + +*** Funções que não recebem argumentos: + +#+begin_src c +int func(void) { + puts("Nada a fazer..."); + return 42; +} +#+end_src + +*** Ponteiros de dados de tipo indeterminado: + +#+begin_src c +void *ptr; +#+end_src + +#+begin_quote +Ponteiros são variáveis que recebem endereços da memória (aula 5). +#+end_quote + +** 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: + +#+begin_src c +(double)5 /* O inteiro '5' será compilado como 'double'. */ +#+end_src + + diff --git a/aulas/03-tipos-de-dados/dump.c b/aulas/03-tipos-de-dados/dump.c new file mode 100644 index 0000000..094abd2 --- /dev/null +++ b/aulas/03-tipos-de-dados/dump.c @@ -0,0 +1,33 @@ +#include + +void print_bytes(char *label, void *addr, size_t size); + +int main(void) { + + int num = 100000; + + int sqr_int = num * num; + unsigned long sqr_long = (unsigned long)num * num; + + print_bytes("num ", &num, sizeof(num)); + printf("-> %d\n", num); + + print_bytes("sqr_int ", &sqr_int, sizeof(sqr_int)); + printf("-> %d\n", sqr_int); + + print_bytes("sqr_long", &sqr_long, sizeof(sqr_long)); + printf("-> %lu\n", sqr_long); + + return 0; +} + + +void print_bytes(char *label, void *addr, size_t size) { + + unsigned char *bytes = (unsigned char *)addr; + + printf("%p - %s - ", bytes, label); + + for (size_t i = 0; i < 8; i++) + printf("%02x ", i > (size - 1) ? 0 : bytes[i]); +} diff --git a/aulas/03-tipos-de-dados/limites.c b/aulas/03-tipos-de-dados/limites.c new file mode 100644 index 0000000..eb66916 --- /dev/null +++ b/aulas/03-tipos-de-dados/limites.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +int main(void) { + + setlocale(LC_NUMERIC, ""); + + puts("Tipo Bytes Limites"); + puts("========================================================================"); + printf("char (%zu) %d a %d\n", sizeof(char), SCHAR_MIN, SCHAR_MAX); + printf("unsigned char (%zu) %d a %d\n", sizeof(unsigned char), 0, UCHAR_MAX); + printf("short (%zu) %'d a %'d\n", sizeof(short), SHRT_MIN, SHRT_MAX); + printf("unsigned short (%zu) %d a %'d\n", sizeof(unsigned short), 0, USHRT_MAX); + printf("int (%zu) %'d a %'d\n", sizeof(int), INT_MIN, INT_MAX); + printf("unsigned int (%zu) %d a %'u\n", sizeof(unsigned int), 0, UINT_MAX); + printf("long int (%zu) %'ld a %'ld\n", sizeof(long int), LONG_MIN, LONG_MAX); + printf("unsigned long int (%zu) %d a %'lu\n", sizeof(long unsigned int), 0, ULONG_MAX); + printf("long long (%zu) %'ld a %'ld\n", sizeof(long long int), LLONG_MIN, LLONG_MAX); + printf("unsigned long long (%zu) %d a %'llu\n", sizeof(unsigned long long int), 0, ULLONG_MAX); + printf("float (%zu) %.2E a %.2E\n", sizeof(float), FLT_MIN, FLT_MAX); + printf("double (%zu) %.2E a %.2E\n", sizeof(double), DBL_MIN, DBL_MAX); + printf("long double (%zu) %.2LE a %.2LE\n", sizeof(long double), LDBL_MIN, LDBL_MAX); + + return 0; +} diff --git a/aulas/03-tipos-de-dados/quadrado-long.c b/aulas/03-tipos-de-dados/quadrado-long.c new file mode 100644 index 0000000..2c887cb --- /dev/null +++ b/aulas/03-tipos-de-dados/quadrado-long.c @@ -0,0 +1,12 @@ +#include + +unsigned long quadrado(long base) { + return base * base; /* Qual é o tipo desse expressão? */ +} + +int main(void) { + long num = 100000; + + printf("%ld^2 = %lu\n", num, quadrado(num)); + return 0; +} diff --git a/aulas/03-tipos-de-dados/quadrado.c b/aulas/03-tipos-de-dados/quadrado.c new file mode 100644 index 0000000..83134af --- /dev/null +++ b/aulas/03-tipos-de-dados/quadrado.c @@ -0,0 +1,12 @@ +#include + +int quadrado(int base) { + return base * base; +} + +int main(void) { + int num = 100000; + + printf("%d^2 = %d\n", num, quadrado(num)); + return 0; +} diff --git a/exercicios/03/README.org b/exercicios/03/README.org new file mode 100644 index 0000000..e69de29