Skip to content

C Language

João Medeiros edited this page Jun 1, 2026 · 11 revisions

Introduction

A linguagem de programação C foi desenvolvida por Dennis Ritchie na Bell Labs a partir de 1972. Ritchie, motivado pela ideia de uma linguagem adequada para re-implementação do sistema operacional Unix, planejou C como uma extensão da linguagem B, com suporte a tipos nativos e definidos pelo usuário. Considere abaixo um programa mínimo escrito na linguagem em acordo com a norma ISO/IEC 9899 (1999, p. 12).

int main(void)
{
    return 0;
}

No trecho acima, temos a definição da função que serve como ponto de entrada para o programa, denominada main(). O primeiro palavra do código int antes do nome da função main indica que o valor retornado pela função será armazenado em uma posição de memória associada a um tipo inteiro. O tipo void em C é usado para explicitar a não necessidade de definição de tipo. Segundo a norma ISO/IEC 9899 (1999, p. 35), esse tipo compreende um conjunto vazio de valores. Dessa forma, a palavra void indica na definição da função denominada main, que a função não deve receber parâmetros. A palavra return indica um ponto de término da função. No código acima, a função main() termina retornando para quem a chamou o valor 0 (zero) armazenado em uma posiçao de memória do tipo int.

Compilation

Antes de ser executado, o código acima precisa ser traduzido para a linguagem de máquina da arquitetura a que se propõe a ser executado. Para isso, é necessário o uso de um programa denominado compilador. Como ilustrado abaixo.

flowchart LR
    X["code.c\n(fonte)"]
    Y["gcc\n(compilador)"]
    Z["code\n(programa)"]
    X -->|input| Y
    Y -->|output| Z
Loading

Assumindo que o código C apresentado é o do arquivo code.c, abaixo é apresentado o uso do compilador GCC em um ambiente Linux.

term@alg$ gcc code.c -o code

O uso da opção -o indica o nome do arquivo a ser gerado como programa executável. Com a utilização do programa hexdump, apresenta-se abaixo o conteúdo dos primeiros 32 bytes dos dois arquivos.

term@alg$ hexdump -C -n 32 code.c
00000000  69 6e 74 20 6d 61 69 6e  28 76 6f 69 64 29 0a 7b  |int main(void).{|
00000010  0a 20 20 20 20 72 65 74  75 72 6e 20 30 3b 0a 7d  |.    return 0;.}|
00000020
term@alg$ hexdump -C -n 32 code
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  03 00 3e 00 01 00 00 00  40 10 00 00 00 00 00 00  |..>.....@.......|
00000020
term@alg$

Na saída referente ao arquivo code.c, persebe-se o conteúdo na representação ASCII dos bytes apresentados. Na saída referente ao arquivo code, tem-se a identificação de um cabeçalho ELF (Executable and Linkable Format). Trata-se de um formato de descrição de arquivos binários (código objeto) utilizado pelo sistema operacional Linux, para o qual o código fonte foi compilado.

Execution

Após o processo de tradução do código fonte em código objeto, é possível executar o programa digitando o caminho do arquivo. Utilizando o diretório especial . do terminal (caminho do diretório corrente), é possível executar o programa com o comando ./code.

term@alg$ ./code
term@alg$

Como nosso programa não produz texto para a saída padrão, o programa é executado pelo sistema operacioal, termina com retorno 0 (zero) e o prompt do terminal é disponibilizado ao usuário novamente. Esse processo pode ser ilustrado pelo diagrama a seguir.

flowchart LR
    X["Bash\n(terminal)"]
    Y["Linux\n(sistema operacional)"]
    X -->|"code (binário)"| Y
    Y -->|"0 (inteiro)"| X
Loading

O terminal aramazena o retorno do programa em uma variável de ambiente denominada $?. É possível verificar o valor de retorno do último programa executado utilizando o programa echo.

term@alg$ echo $?
0
term@alg$

No trecho acima é possível verificar que o valor da variável de ambiente $? é 0 (zero), como esperado.

Language

A linguagem C geralmente possui mais de uma forma realizar desvio de fluxo de execução e laço de repetição. Aqui, serão descritos o condicional if e o laço while.

Conditional

Na linguagem C, o valor 0 (zero) é considerado como falso em testes condicionais. Qualquer coisa diferente de 0 (zero) é considerada verdadeira.

flowchart LR
    c{c não é 0?}
    A --> c
    c -->|sim| B
    c -->|não| C
    B --> D
    C --> D
Loading
// [A]
if (c)
{
    // [B]
}
else
{
    // [C]
}
// [D]

Loop

flowchart LR
    c{c não é 0?}
    A --> c
    c -->|sim| B
    c -->|não| C
    B --> c
Loading
// [A]
while (c)
{
    // [B]
}
// [C]

Types

  • int: tipo básico de inteiro com sinal (capaz de representar o intervalo [−32767, +32767]).
  • float: tipo básico de real com sinal (capaz de representar em módulo o intervalo [1.175494e-38, 3.402823e+38]).
  • char: inteiro usado para representação de caracteres (capaz de representar a tabela ASCII).

Struct (composition)

flowchart TB
  subgraph point["struct point"]
    c["float x;\nfloat y;"]
  end
Loading
struct point
{
    float x;
    float y;
};
flowchart TB
  subgraph circle["struct circle"]
    subgraph point["struct point origin;"]
      p["float x;\nfloat y;"]
    end
    c["float radius;"]
  end
Loading
struct circle
{
    struct point origin;
    float radius;
};

Address (pointer)

É possível utilizar o qualificador de tipo * para dizer que uma variável guarda o endereço de uma variável que armazena aquele tipo. Por exemplo, considere o código abaixo.

int main()
{
    int a;
    int *p;

    a = 42;
    p = &a;
    printf("%p\n", p);
    printf("%d\n", *p);
    *p = 21;
    printf("%d\n", a);

    return 0;
}

No arquivo pointer.c acima, é declarada uma variável a do tipo int. Em seguida, é declarada uma variável p do tipo int *. A variável p deve armazenar o endereço de uma variável de tipo int. Após a declaração de p, é armazenado o valor 42 em a e é armazenado em p o endereço da variável a utilizando o operador de endereço &. Na chamada printf() logo após, é utiliza-se %p para imprimir na saída padrão o valor armazenado em p. Na chamada printf() seguinte, utiliza-se o operador conteúdo * para recuperar o valor armazenado na posição de memória contida na variável p e imprimi-lo na saída padrão (deve-se notar a utilização de %d dessa vez, uma vez que o conteúdo da posição de memória armazeda em p é do tipo int). Em seguida, o valor contido na variável a é alterado de forma indireta pela expressão *p = 21;. Essa instrução faz com que se armazene o valor 21 como conteúdo da posição de memória armazenada em p. Para verificar a alteração, utiliza-se uma última vez a função printf() para imprimir na saída padrão o valor contido na variável a. Veja a saída do programa abaixo.

term@alg$ cc -Wall pointer.c -o pointer
term@alg$ ./pointer
0x7ffd24143ea4
42
21

References

ISO/IEC 9899:1999 - Programming languages - C
GCC - the GNU Compiler Collection
ASCII Table
C Data Types

Clone this wiki locally