mirror of
https://gitlab.com/blau_araujo/cblc.git
synced 2025-06-07 12:06:37 -03:00
Alvaro: Resolução dos exercícios da aula 3 #13
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Exercícios da aula 3: Tipos de dados
1. Pesquise e demonstre
No programa
quadrado-long.c
, da aula 2, encontre uma forma de demonstrar o tipo do valor avaliado pela expressãobase * base
nesta função:Solução
Saída:
Explicação
No programa
quadrado-long.c
, a expressãobase * base
é avaliada como um valor do tipolong
, porque ambos os operandos (base
) são do tipolong
.Podemos usar o operador
sizeof
e_Generic
(disponível em C11) para inspecionar o tipo em tempo de compilação.Como
base
élong
, o resultado é o produto delong
porlong
, portantolong
.O retorno
unsigned long
da funçãoquadrado
só ocorre após a multiplicação, caso em que o tipo da expressão é convertido paraunsigned long
.Se
base
for muito grande (ex: 2.000.000.000),base * base
pode estourar (já quelong
tem limite). Nesse caso, mesmo retornandounsigned long
, o cálculo intermediário (long * long
) já terá ocorrido com overflow.2. Desafio: conversão de Fahrenheit para Celsius
Criar um programa que converta valores inteiros de -100ºF a 100ºF para Celsius e apresente os resultados no terminal.
Fórmula da conversão:
C = 5 × (F - 32) / 9
Os valores em Fahrenheit serão expressos pela variável
i
, declarada no loopfor
.Por exemplo:
Solução
3. Pesquise e responda
O operador
sizeof(TIPO)
expressa o tamanho em bytes deTIPO
com o tiposize_t
.O que é o tipo
size_t
?size_t
é um tipo de dado inteiro sem sinal (unsigned) definido pela linguagem C para representar tamanhos de objetos em bytes. Ele é usado principalmente para retornar o resultado desizeof()
, representar índices e tamanhos em funções de manipulação de memória (malloc
,memcpy
, etc) e evitar problemas de portabilidade, já que seu tamanho varia conforme a arquitetura (32-bit ou 64-bit).Como utilizá-lo no seu programa sem incluir cabeçalhos?
Se você não quiser incluir
<stddef.h>
ou<stdio.h>
, pode declararsize_t
manualmente no seu programa, mas isso não é recomendado, pois o tamanho exato desize_t
depende do compilador e do sistema. Sem os cabeçalhos padrão perde-se a portabilidade.Em quais cabeçalhos ele é definido?
size_t
é definido nos seguintes cabeçalhos padrão:<stddef.h>
(Definição principal)<stdio.h>
(Para funções de I/O comoprintf
)<stdlib.h>
(Para funções comomalloc
)<string.h>
(Para funções comostrlen
)Exemplo de uso recomendado:
Qual é o especificador de formatos para ele no
printf
?O especificador correto para
size_t
noprintf
é%zu
(recomendado, portável e seguro).Exemplo de uso recomendado:
Alternativas (não portáveis e não recomendadas):
%lu
(sesize_t
forunsigned long
)%u
(sesize_t
forunsigned int
)Essas alternativas devem ser evitadas, pois elas podem causar comportamento indefinido em sistemas onde
size_t
não corresponde ao tipo assumido.4. Compile, corrija e responda
O programa abaixo deveria imprimir 0.25 no terminal…
Responda:
Depois de compilado e executado, qual foi o valor impresso?
O programa imprime 0 e não 0.25 como esperado.
Por que isso aconteceu?
O problema está na linha
"int valor = 1 / 4;"
, pois ocorre uma divisão inteira, já queint / int = int
.Quando ambos os operandos são inteiros (1 e 4), o C realiza uma divisão inteira, descartando a parte fracionária.
1 / 4
resulta em quociente 0 e resto 1, por isso o resultado foi 0.Como solucionar?
Existem pelo menos 2 formas de corrigir.
Solução 1. Usar
float
oudouble
em pelo menos um operando decimal, pois se um dos operandos é de ponto flutuante (float
/double
), a divisão será de ponto flutuante.Exemplo:
Solução 2. Converter explicitamente um operando para
float
/double
usando casting.Exemplo:
5. Analise, pesquise e comente o código
Programa dump.c:
Solução
Saída:
Observações:
Em
"(unsigned long)num * num;"
o cast força a multiplicação a ser feita emunsigned long
(64 bits), evitando overflow.A função
print_bytes
converteaddr
paraunsigned char*
(byte a byte).Saídas esperadas para
num = 100000
(little-endian):num
(int
, 4 bytes):0x000186a0
→ Bytes:a0 86 01 00
a0 86 01 00 00 00 00 00
sqr_int
(overflow):10.000.000.000
em 32 bits é truncado para0x540BE400
e vira o decimal1.410.065.408
. Bem menor que o valor esperado.00 e4 0b 54 00 00 00 00
sqr_long
(64 bits):10.000.000.000
em 64 bits é representado integralmente como0x00000002540BE400
00 e4 0b 54 02 00 00 00
Problemas e soluções:
Overflow em
sqr_int
:int
(32 bits) não consegue armazenar10.000.000.000
long long
ouunsigned long
desde o inícioPortabilidade:
long
varia (32/64 bits)uint64_t
(do<stdint.h>
) para precisãoSugestões de Melhoria
1. Adicionar Verificação de Overflow:
2. Usar Tipos de Tamanho Fixo: