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 1 #8
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?
Estou compartilhando a minha resolução para críticas, complementações e crescimento mútuo.
Linguagem C: Conceitos e Exercícios
1. Pesquise e explique.
As classificações abaixo são utilizadas para descrever as características da linguagem C: pesquise e explique cada uma delas.
a. Linguagem de alto nível
É uma linguagem mais abstrata e mais fácil de entendimento para os humanos. Ela se concentra em conceitos mais próximos da linguagem humana como variáveis, loops e funções. As linguagens de alto nível são usadas para a maioria das aplicações de programação. Elas são mais fáceis de aprender e usar do que as linguagens de baixo nível, e permitem que os programadores se concentrem no algoritmo do programa, deixando os detalhes técnicos para a linguagem de programação.
b. Linguagens Compilada
É aquela em que o código fonte é traduzido para uma linguagem de baixo nível antes da execução, gerando um arquivo que pode ser executado diretamente pelo sistema operacional. O processo de compilação pode levar mais tempo que o processo de interpretação, mas o código resultante tende a ser mais rápido e eficiente em termos de recursos.
c. Linguagem Procedural
Se baseia no conceito de procedimentos, que são conjuntos de instruções que dizem ao computador o que fazer passo a passo. Algumas características são estruturas de controle que direcionam o fluxo de execução do programa, modularidade que permite dividir o programa em partes menores para organização e reutilização do código e encapsulamento que oculta complexidades, combinando dados e funções em um módulos, reduzindo a complexidade.
d. Linguagem imperativa
Se baseia em descrever detalhadamente o passo a passo de um processo que a máquina deve executar, ou seja, as instruções são passadas por meio de códigos na sequência que devem ser executadas.
e. Linguagem estruturada
Visa a qualidade, clareza e eficiência de programas por meio da utilização de sub-rotinas e três estruturas básicas: sequência, seleção (if e switch) e iteração (laços for e while), evitando ou proibindo saltos incondicionais no código pelo uso do comando "goto", pois isso costuma tornar o código confuso e difícil de manter.
2. Analise o programa.
Dado o programa abaixo (salve.c), explique cada uma perguntas nos comentários.
a. #include <stdio.h> // O que é isso e para que serve?
O código-fonte é o código do programa escrito numa linguagem de programação, ele é legível para humanos, mas incompreensível para o computador. O compilador é um programa que traduz o código-fonte para o código objeto e transforma o código objeto em código executável. O código objeto é o código em linguagem de máquina, mas ainda incompleto e incapaz de funcionar. O código executável é o código completo e capaz de ser executado pelo sistema operacional, por ser o resultado da ligação do código objeto com bibliotecas externas e outras dependências. O pré-processador é um programa auxiliar que roda antes do compilador, preparando o código-fonte para a compilação. O símbolo # no início de linha indica uma diretiva de pré-processador, como: #include, #define e #ifdef. A diretiva #include indica que o compilador deve incluir o conteúdo de determinado arquivo. Os limitadores <> indicam que o arquivo deve ser procurado nas pastas padrão do sistema, enquanto os limitadores "" indicam que o arquivo deve primeiro ser procurado na pasta do programa e depois nas pastas padrão. O nome de arquivo stdio vem de standard input/output e h de header file. O arquivo stdio.h contém declarações de funções de entrada e saída padrão construídas em cima da biblioteca padrão do sistema operacional. A biblioteca padrão traduz funções de alto nível em chamadas de sistema usando a API do sistema operacional.
b. Por que todo o programa é escrito na função 'main()'?
Porque a função main é o porta de entrada e de saída de um programa em C. Pode haver funções auxiliares fora da função main, mas o sistema operacional não pode acessá-las diretamente, ele só as acessa se houver chamadas a elas dentro da função main. A função main coordena toda a execução do programa, isto é, a execução de comandos contidos dentro dela e as chamadas a funções externas.
c. O que faz e como se usa a função 'puts()'?
A função puts, put string, imprime uma string na tela e adiciona uma quebra de linha no final. Ela é uma instrução de saída padrão que é declarada quando o pré-processador inclui o conteúdo do arquivo stdio.h no código do programa. A função puts recebe como argumento strings entre aspas duplas ou variáveis do tipo char[]. A função puts não é capaz de lidar com variáveis numéricas ou não textuais.
d. return 0; // Para que serve esta instrução?
Ela serve para informar ao sistema operacional que a execução do programa terminou corretamente sem erros. O valor 0 significa que tudo terminou como esperado, qualquer valor diferente de zero indica erro ou uma situação diferente do normal. O sistema operacional usa esse retorno para agir de acordo, por exemplo, em scripts que executam vários programas o sistema operacional usa esse retorno para saber se o programa anterior terminou bem para poder rodar o próximo. Em sistemas baseados em Unix é padrão considerar 0 como sucesso e qualquer outro valor como erro. Em alguns compiladores do C moderno é assumido que o retorno é 0 mesmo que o comando não seja colocado, mas é uma boa prática colocar o comando explicitamente ao final da função main.
3. Compile, encontre, explique e corrija os bugs.
O uso de números mágicos (valores literais que não dão pistas de seus significados) é desaconselhado porque dificultam a leitura semântica do código. Sendo assim, nós utilizaremos a constante simbólica EXIT_SUCCESS, definida na biblioteca padrão com valor 0, em vez do inteiro literal 0 como argumento da instrução return:
Observe o resultado da compilação:
a. Quantos erros foram encontrados e quais são eles?
O primeiro erro ocorreu na linha 5, caractere 12.
O segundo erro na linha 5, caractere 24.
O compilador também fez sugestões sobre o tratamento dos erros.
A correção sugerida ao tratamento do primeiro erro deveria ser posta na linha 2, caractere 1.
A correção sugerida ao tratamento do segundo erro deveria ser posta na linha 5, caractere 24.
Houve também o aviso de que o compilador indica o identificador não declarado apenas uma vez para cada função que ele aparece. Isso é feito para evitar poluir a tela com o mesmo erro repetido várias vezes na mesma função.
b. Quais são as correções sugeridas pelo gcc?
A primeira correção diz que EXIT_SUCCESS está definico no arquivo de cabeçalho stdlib.h e sugere escrever #include <stdlib.h> na linha 2, caractere 1.
A segunda correção diz que o caractere ; era esperado antes do símbolo } e sugere escrever um ; na linha 5, caractere 24.
c. Como ficou o código corrigido?
4. Compile, pesquise e responda.
Dado o código abaixo (por exemplo, main.c):
Compilação:
a. Nenhum erro foi reportado, mas por quê?
Primeiro motivo. O código de main.c não inclui o arquivo stdio.h, mas declara a função puts manualmente para o compilador. Por isso, o compilador aceita a chamada da função puts mesmo sem saber onde ela está definida, nem o seu código. O compilador só sabe o nome da função puts, que ela recebe um ponteiro para uma string constante e que retorna um inteiro. O código real da função puts é buscado na etapa de ligação pelo linker na biblioteca padrão do C.
Segundo motivo. O código de main.c não inclui o arquivo stdlib.h, mas define manualmente a constante EXIT_SUCCESS como 0. Assim o compilador sabe que toda vez que encontrar a constante EXIT_SUCCESS deve substituí-la por 0.
Em programas reais é uma boa prática incluir stdio.h e stdlib.h, pois esses arquivos garantem que o compilador use as declarações corretas, portáveis e padronizadas de funções e constantes. Declarar funções e constantes manualmente pode causar erros, incompatibilidades, falta de portabilidade e bugs difíceis de identificar, principalmente em projetos grandes ou ao trocar de plataforma.
b. Como você executaria o binário resultante?
5. Pesquise e responda
Quando não explicitamos a especificação utilizada para compilar o nosso programa (opção -std=PADRÃO do gcc), qual será o padrão utilizado e como podemos confirmar isso pela linha de comandos?
O padrão depende da versão do GCC, mas hoje geralmente é gnu17.
Isso pode ser confirmado pelo comando:
Se a resposta for
#define __STDC_VERSION__ 201710L
indica que o padrão é C17, 201710L = outubro de 2017, data em que o padrão C17 foi finalizado.Para garantir um padrão específico o comando é:
Minha resolução dos exercícios da aula 1to Alvaro: Resolução dos exercícios da aula 1