Aula 29 – struct em C vs class em Java

Como C agrupa dados em registros — e por que é diferente (e mais simples) do que uma classe Java

Por que precisamos de um jeito de agrupar dados?

Imagine que você quer representar um aluno no seu programa. Ele tem matrícula, nome e nota. Em Java, você faria isso com uma classe. Em C, você usa uma struct (estrutura).

Uma struct (abreviação de structure) é uma forma de criar um tipo composto em C: um agrupamento de variáveis de tipos diferentes sob um único nome. Cada variável dentro da struct é chamada de campo (ou field).

Antes de ver a sintaxe, compare os dois mundos lado a lado:

Java — class C — struct
Agrupa dados + métodos Agrupa só dados (campos)
Tem construtores, herança, polimorfismo Não tem nada disso — apenas campos
Objetos ficam no heap; variável guarda referência Struct pode ficar na stack; variável é o dado em si
Criado com new NomeDaClasse() Declarado como qualquer variável: REGISTRO r;
Acessa campos com objeto.campo Acessa campos com variavel.campo ou ponteiro->campo
Resumo rápido: Uma struct em C é como uma classe Java sem métodos, sem construtores e sem herança. É o bloco de construção mais básico para organizar dados relacionados.

Sintaxe da struct em C

A forma mais simples de declarar uma struct:

struct NomeDaEstrutura {
    tipo campo1;
    tipo campo2;
    // ... mais campos
};

Exemplo concreto — um aluno com matrícula e nota:

#include <stdio.h>

struct Aluno {
    int    matricula;
    float  nota;
};

int main() {
    struct Aluno a;          // declara uma variável do tipo struct Aluno
    a.matricula = 1001;      // acessa o campo com o operador ponto (.)
    a.nota      = 8.5;

    printf("Matrícula: %d\n", a.matricula);
    printf("Nota:      %.1f\n", a.nota);
    return 0;
}

Matrícula: 1001

Nota: 8.5

Note o struct antes do nome: Em C "puro" (sem typedef), para declarar uma variável você precisa escrever struct Aluno a; — o struct faz parte do nome do tipo. Na próxima aula veremos como o typedef elimina essa repetição.

Comparação direta com Java

Veja o mesmo "cadastro de aluno" nas duas linguagens:

☕ Java
class Aluno {
    int   matricula;
    float nota;

    Aluno(int m, float n) {
        this.matricula = m;
        this.nota = n;
    }

    void exibir() {
        System.out.println(
          matricula + " — " + nota);
    }
}

// Uso:
Aluno a = new Aluno(1001, 8.5f);
a.exibir();
⚙️ C
struct Aluno {
    int   matricula;
    float nota;
};
// Sem construtor, sem métodos.
// Funções ficam fora da struct.

void exibir(struct Aluno a) {
    printf("%d — %.1f\n",
           a.matricula, a.nota);
}

// Uso:
struct Aluno a = {1001, 8.5f};
exibir(a);
Diferença crítica — onde ficam as funções? Em Java, os métodos pertencem à classe. Em C, as funções são separadas — elas recebem a struct como parâmetro. Esse é o ponto mais importante desta aula: C separa dados (struct) de comportamento (funções).

Structs dentro de Structs

Assim como em Java uma classe pode ter atributos de outras classes, em C uma struct pode ter campos que são outras structs:

typedef int TIPOCHAVE;   // veremos typedef melhor na próxima aula

typedef struct {
    TIPOCHAVE chave;     // campo "chave" — o identificador do registro
    // outros campos poderiam vir aqui: nome, data, etc.
} REGISTRO;

typedef struct {
    REGISTRO A[50];      // array de até 50 registros
    int      nroElem;    // quantos elementos estão ocupados
} LISTA;

Essa é exatamente a estrutura que usaremos nas próximas aulas para implementar uma lista linear sequencial. A LISTA contém um array de REGISTROs, e cada REGISTRO tem uma chave do tipo TIPOCHAVE.

Em Java, o equivalente seria uma classe Lista que contém um array de objetos Registro[], e cada Registro tem um campo int chave. Mesma ideia — sintaxe diferente.

Formas de Inicializar uma Struct

C oferece diferentes formas de criar e preencher uma struct:

struct Aluno {
    int   matricula;
    float nota;
};

int main() {
    // Forma 1: declarar e atribuir campo a campo
    struct Aluno a1;
    a1.matricula = 1001;
    a1.nota = 8.5f;

    // Forma 2: inicialização por posição (C89 em diante)
    struct Aluno a2 = {1002, 7.0f};

    // Forma 3: inicialização por nome de campo (C99 em diante — mais segura)
    struct Aluno a3 = { .matricula = 1003, .nota = 9.5f };

    printf("a1: %d | %.1f\n", a1.matricula, a1.nota);
    printf("a2: %d | %.1f\n", a2.matricula, a2.nota);
    printf("a3: %d | %.1f\n", a3.matricula, a3.nota);
    return 0;
}

a1: 1001 | 8.5

a2: 1002 | 7.0

a3: 1003 | 9.5

Boa prática: Prefira a Forma 3 (designated initializers) quando possível — ela é mais legível e não depende da ordem dos campos na struct.

Exercícios — Aula 29

Responda às questões para fixar o conceito de struct:

1. O que uma struct em C não pode conter, ao contrário de uma class em Java?

2. Dado o código abaixo, qual linha está correta?

struct Ponto { int x; int y; };
struct Ponto p = {3, 7};

3. Em C, como se acessa o campo nota de uma variável struct Aluno a?

4. Qual afirmação sobre o design de C é verdadeira?

5. Na estrutura abaixo, o que representa o campo nroElem?

typedef struct {
    REGISTRO A[50];
    int nroElem;
} LISTA;

6. Qual é a forma de inicialização por nome de campo (C99) para struct Aluno { int matricula; float nota; }?

7. Em Java, quando você faz Aluno a = new Aluno(), o objeto fica no heap e a é uma referência. Em C, quando você faz struct Aluno a;, onde a struct fica (por padrão)?

8. Analise o código. Qual será a saída?

struct Par { int a; int b; };
struct Par p = { .b = 10, .a = 3 };
printf("%d %d\n", p.a, p.b);