paulo1205
(usa Ubuntu)
Enviado em 13/05/2019 - 03:10h
C e C++ são linguagens pensadas para computadores genéricos. Essas linguagens exigem do computador apenas as seguintes características:
• conseguir armazenar e recuperar valores na memória;
• poder representar dados de certos tipos determinados, a saber: números inteiros (dos quais caracteres são casos particulares), números de ponto flutuante, e um tipo que possa ser usado para endereçar a memória;
• ser capaz de executar certo conjunto finito de operações aritméticas e lógicas;
• permitir desvios do fluxo de execução do programa, que podem ser incondicionais (
goto,
break,
continue), condicionais (
if/
else,
while,
do-
while,
swicth) e invocação de funções.
As linguagens nem ao menos exigem que essas operações sejam mapeadas de forma direta para operações nativas de algum tipo de máquina. Um PC cujo processador tem como mapear nativamente todas as características acima é tão válido como alvo quanto uma pessoa que usa cadernos como memória e como form de acompanhar o estado atual de execução do programa, e lápis para alterar os valores dessa memória e estado durante execução.
Um passo além da linguagem pura e simples, os padrões do C e do C++ definem o comportamento de programas que executem sob uma implementação “hospedada” por algo parecido com um sistema operacional. As operações requeridas do ambiente hospedado não estão em nível de linguagem, mas são realizadas por meio de tipos de dados e funções com nomes padronizados, que são parte da biblioteca padrão associada à linguagem. Nessas implementações, a lista de exigências cresce um pouco, incluindo o seguinte:
• receber do ambiente hospedeiro informações que possam modificar o comportamento da execução do programa, bem como devolver um código que possa indicar o grau de sucesso da execução do programa (através da função
main(), mas também
exit(),
abort() e outras);
• poder alocar e desalocar dinamicamente quantidades de memória que só serão conhecidas no momento da execução do programa (
malloc(),
realloc(),
free() e funções relacionadas, ou
containers do C++);
• manipular
strings de caracteres, usando uma representação de
strings que também é definida pelo padrão (todas as funções em <string.h>, ou <string> do C++);
• executar operações matemáticas além daquelas implementadas em nível de linguagem, tais cálculo de valor absoluto, funções exponenciais, logarítmicas, trigonométricas e transcendentais etc. (em <stdlib.h> e <math.h>);
• realizar entrada e saída de dados, inclusive a partir de meios de armazenamento que possam manter tais dados por tempo maior do que a duração do programa (em <stdio.h>, ou <iostream>, <fstream> e relacionados em C++);
• implementar meios de invocar o ambiente de execução hospedeiro, para que ele possa ser capaz de executar operações arbitrárias (e.g.
system());
• representar e manipular dados de data e hora (em <time.h>,);
• permitir a manipulação de argumentos individuais em funções com número variável de argumentos (em <stdarg.h>).
Apesar da lista de maior tamanho, o computador alvo dessa especificação continua bastante genérico. Por exemplo, mesmo introduzindo o conceito de arquivos identificados por nomes em <stdio.h>, não há especificação de onde nem de como esses arquivos venham a ser armazenados, nem como ele pode persistir por tempo maior do que o da duração da execução do programa em C ou C++.
Esse computador genérico é útil em muitos sentidos, incluindo na capacidade de criar programas que produzam comportamento idêntico em múltiplas implementações, pelo menos do ponto de vista do programa em C ou C++. Contudo, dentre os itens elencados acima, um em particular abre a porta para a produção de comportamentos diferentes por diferentes hospedeiros: a função
system(). Isso se dá porque o argumento dessa função é um comando que é executado por cada hospedeiro fora do escopo do programa em C ou C++, de modo que é possível (e, na prática, muito comum) que diferentes hospedeiros não reconheçam os mesmos comandos, ou que produzam resultados diferentes sob diferentes condições de execução em diferentes momentos.
Frequentemente é necessário fazer com que o programa em C ou C++ execute mais coisas do que apenas as funções do computador genérico. Seja para lidar com um tipo de dispositivo específico de um computador real, seja para dar ao usuário uma experiência mais agradável (através de uma interface interativa ou gráfica, por exemplos), seja para lidar com detalhes de implementação, é muito comum que o programa tenha de recorrer a algum meio de interagir com o computador específico em que executa para executar funções que lhe são específicas.
Nesses casos, às vezes basta invocar
system() com o argumento certo para o hospedeiro em questão. Contudo, o conjunto de operações que costuma estar disponível para o uso dessa maneira costuma ser muito pequeno quando comparado a todos os recursos que o hospedeiro pode oferecer. Além disso, frequentemente é muito custoso executar qualquer coisa através essa função, e ainda existe o problema de que o programa que chama
system() fica parado até que a solicitação feita ao hospedeiro esteja totalmente concluída.
O que muitos programas que precisam de recursos específicos da máquina fazem é complementar a funcionalidade padronizada com bibliotecas de funções e tipos específicas do sistema hospedeiro que implementem as funções específicas desse hospedeiro nas quais o programador tem interesse.
... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)