UC00669

Programação em C/C++ — básico

Sintaxe, pointers, structs, ficheiros

Curso profissional · 50h · Linguagens de sistema

Plano

  1. C vs C++ — quando usar
  2. Setup e Hello World
  3. Sintaxe C básica
  4. Pointers e memória
  5. Arrays e strings
  6. Structs
  7. Funções e modularização
  8. Ficheiros
  9. Introdução a C++

Bloco 1 · Contexto

Por que aprender C/C++

  • Linguagens de sistema — kernels, drivers, embedded.
  • Performance máxima — controlo total da memória.
  • Base para Linux, Windows, jogos AAA, motores 3D.
  • Embedded — Arduino, microcontroladores, IoT.
  • Salários altos em embedded, jogos, finanças.

Curva difícil, mas conceitos compensam para sempre.

C vs C++

C C++
Procedural OOP + procedural + functional
Sintaxe simples Mais features (e complexidade)
printf cout (ou printf)
malloc / free new / delete ou smart pointers
Kernels, embedded Jogos, sistemas grandes

C é subset (quase) de C++. Vamos começar por C e depois ver C++.

Setup

# Linux/Mac: já tens gcc/g++
gcc --version
g++ --version

# Windows: instalar MSYS2 ou WSL
# Ou MinGW

# IDE: VSCode + extensão C/C++
# Ou CLion (JetBrains, pago)
# Ou Code::Blocks (gratuito)

Hello World em C

// hello.c
#include <stdio.h>

int main() {
    printf("Olá mundo!\n");
    return 0;
}
gcc hello.c -o hello
./hello

#include <stdio.h> = importa funções de I/O.
return 0 = sucesso.

Bloco 2 · Sintaxe C

Tipos primitivos

int idade = 25;              // 4 bytes
long populacao = 8000000000L;
short pequeno = 100;
char letra = 'A';            // 1 byte, ASCII
float taxa = 0.21f;
double preco = 9.99;

// sem tipo string nativo — usa-se char[]
char nome[] = "Ana";
sizeof(int);      // 4
sizeof(double);   // 8
sizeof(char);     // 1

printf e scanf

#include <stdio.h>

int main() {
    int idade;
    char nome[50];
    
    printf("Nome: ");
    scanf("%s", nome);     // sem & em arrays
    
    printf("Idade: ");
    scanf("%d", &idade);   // & = endereço de
    
    printf("Olá, %s! Tens %d anos.\n", nome, idade);
    return 0;
}

Format specifiers: %d (int), %f (float), %s (string), %c (char), %lf (double).

Operadores

// Aritméticos: + - * / %
int divisao = 10 / 3;       // 3 (int)
double real = 10.0 / 3;     // 3.333

// Atribuição composta
int x = 10;
x += 5;     // 15
x++;        // 16
++x;        // 17

// Comparação
a == b      // igual
a != b      // diferente
a < b, >, <=, >=

// Lógicos
&& ||  !

// Bitwise
&  |  ^  ~  <<  >>

Estruturas controlo

// If
if (idade >= 18) {
    printf("Adulto\n");
} else if (idade >= 13) {
    printf("Adolescente\n");
} else {
    printf("Criança\n");
}

// Switch
switch (dia) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        printf("Útil\n");
        break;
    case 6:
    case 7:
        printf("Weekend\n");
        break;
    default:
        printf("Inválido\n");
}

Loops

// For
for (int i = 0; i < 10; i++) {
    printf("%d\n", i);
}

// While
int i = 0;
while (i < 5) {
    printf("%d\n", i);
    i++;
}

// Do-while
do {
    // pelo menos uma vez
} while (cond);

// Break e continue
for (int i = 0; i < 100; i++) {
    if (i == 50) break;
    if (i % 2 == 0) continue;
    printf("%d\n", i);
}

Bloco 3 · Arrays e Strings

Arrays

int numeros[5] = {1, 2, 3, 4, 5};
int vazio[10];   // sem inicializar — lixo!
int auto[] = {1, 2, 3};   // tamanho inferido

// Acesso
numeros[0] = 10;
int primeiro = numeros[0];

// Tamanho (em compile-time)
int tamanho = sizeof(numeros) / sizeof(int);

// Iterar
for (int i = 0; i < 5; i++) {
    printf("%d\n", numeros[i]);
}

// CUIDADO: sem bounds check!
// numeros[100] = 0;  // crash ou corrupção

Strings (char arrays)

#include <string.h>

char nome[50] = "Ana";

// strlen — comprimento
int len = strlen(nome);   // 3

// strcpy — copiar
char outro[50];
strcpy(outro, nome);

// strcat — concatenar
char saudacao[100] = "Olá, ";
strcat(saudacao, nome);   // "Olá, Ana"

// strcmp — comparar
if (strcmp(nome, "Ana") == 0) {
    printf("É a Ana!\n");
}

// fgets (mais seguro que scanf)
char linha[100];
fgets(linha, 100, stdin);

Strings terminam com '\0' (null terminator).

Bloco 4 · Pointers

O que é um pointer

Pointer = variável que guarda um endereço de memória.

int x = 42;
int *p = &x;     // p aponta para x

printf("%d\n", x);   // 42
printf("%d\n", *p);  // 42 (deref)
printf("%p\n", p);   // 0x7ffe... (endereço)

*p = 100;        // x agora vale 100
printf("%d\n", x);   // 100

& = endereço de.
* = valor apontado por (deref).

Pointers e arrays

int arr[5] = {10, 20, 30, 40, 50};

int *p = arr;    // p aponta para arr[0]
printf("%d\n", *p);      // 10
printf("%d\n", *(p+1));  // 20
printf("%d\n", p[2]);    // 30 (mesma coisa)

// Aritmética de pointers
p++;             // próximo int
printf("%d\n", *p);  // 20

Array é (quase) pointer ao primeiro elemento.

Memória dinâmica

#include <stdlib.h>

// malloc — aloca memória
int *arr = (int *) malloc(10 * sizeof(int));
if (arr == NULL) {
    // sem memória!
    return 1;
}

arr[0] = 42;
arr[9] = 99;

// free — liberta!
free(arr);
arr = NULL;  // boa prática

Cada malloc precisa de um free. Memory leaks são um problema clássico em C.

Bloco 5 · Funções

Definição e chamada

// Declaração (prototype) — opcional se definido antes
int somar(int a, int b);

// Definição
int somar(int a, int b) {
    return a + b;
}

int main() {
    int resultado = somar(2, 3);
    printf("%d\n", resultado);   // 5
    return 0;
}

Passar por valor vs por referência

// Por valor — cópia
void incrementa(int n) {
    n++;  // só altera cópia local
}

// Por referência (pointer) — altera original
void incrementa_real(int *n) {
    (*n)++;
}

int main() {
    int x = 5;
    incrementa(x);
    printf("%d\n", x);   // 5 (não mudou)
    
    incrementa_real(&x);
    printf("%d\n", x);   // 6
}

Modularização

Header (utils.h):

#ifndef UTILS_H
#define UTILS_H

int somar(int a, int b);
int maximo(int a, int b);

#endif

Implementação (utils.c):

#include "utils.h"

int somar(int a, int b) { return a + b; }
int maximo(int a, int b) { return a > b ? a : b; }

Main (main.c):

#include <stdio.h>
#include "utils.h"

int main() {
    printf("%d\n", somar(2, 3));
}

Compilar:

gcc main.c utils.c -o programa

Bloco 6 · Structs

Definição

struct Pessoa {
    char nome[50];
    int idade;
    double altura;
};

int main() {
    struct Pessoa p1;
    strcpy(p1.nome, "Ana");
    p1.idade = 25;
    p1.altura = 1.65;
    
    printf("%s, %d anos, %.2fm\n", p1.nome, p1.idade, p1.altura);
    
    // Initializer
    struct Pessoa p2 = {"Bruno", 30, 1.80};
    return 0;
}

typedef

typedef struct {
    char nome[50];
    int idade;
} Pessoa;

// Agora sem "struct"
Pessoa p1 = {"Ana", 25};
Pessoa *ptr = &p1;
ptr->idade = 26;   // -> para acesso via pointer

-> = deref + access (igual a (*ptr).idade).

Bloco 7 · Ficheiros

Ler ficheiro

#include <stdio.h>

int main() {
    FILE *f = fopen("dados.txt", "r");
    if (f == NULL) {
        perror("Erro");
        return 1;
    }
    
    char linha[256];
    while (fgets(linha, sizeof(linha), f) != NULL) {
        printf("%s", linha);
    }
    
    fclose(f);
    return 0;
}

Sempre fechar com fclose. Modos: "r", "w", "a", "r+", "rb" (binário).

Escrever ficheiro

FILE *f = fopen("output.txt", "w");
if (f == NULL) {
    perror("Erro");
    return 1;
}

fprintf(f, "Olá mundo!\n");
fprintf(f, "Número: %d\n", 42);

fclose(f);

"w" = sobrescreve; "a" = append.

Bloco 8 · C++

C++ vs C — diferenças básicas

// hello.cpp
#include <iostream>
using namespace std;

int main() {
    cout << "Olá mundo!" << endl;
    
    string nome;
    cout << "Nome: ";
    cin >> nome;
    cout << "Olá, " << nome << "!" << endl;
    
    return 0;
}
g++ hello.cpp -o hello
./hello
  • iostream em vez de stdio.h.
  • cout / cin em vez de printf / scanf.
  • string em vez de char[].

Classes em C++

class Pessoa {
private:
    string nome;
    int idade;
    
public:
    Pessoa(string n, int i) : nome(n), idade(i) {}
    
    void apresentar() {
        cout << "Olá, sou " << nome << endl;
    }
    
    string getNome() const { return nome; }
};

int main() {
    Pessoa p("Ana", 25);
    p.apresentar();
}

std::vector — alternativa a arrays

#include <vector>
#include <iostream>
using namespace std;

int main() {
    vector<int> nums = {1, 2, 3, 4, 5};
    nums.push_back(6);
    nums.pop_back();
    
    for (int n : nums) {
        cout << n << " ";
    }
    cout << endl;
    
    cout << "Size: " << nums.size() << endl;
}

vector = array dinâmico, sem malloc/free.

UC00669 · resumo

  • C é a base — sintaxe minimalista, controlo total.
  • Pointers são poderosos mas perigosos — entender bem.
  • malloc/free sempre em pares.
  • Strings em C são char[] terminados em \0.
  • Structs + typedef para tipos compostos.
  • Ficheiros com fopen/fclose.
  • C++ adiciona OOP, strings, vectors, exceptions.
  • Base para embedded, sistemas, jogos, kernels.