Publicidade

Structs (struct)

Defina structs, acesse membros, combine com arrays e use typedef e enum.

📖 O que você vai aprender nesta página
✅ Essenciais que você precisa saber
  • struct Point { int x, y; }; agrupa campos relacionados
  • Acesse membros com p.x
  • Inicialize com struct Point p = {3, 4};
⭐ Leia se tiver tempo
  • Através de um ponteiro: p->x (o mesmo que (*p).x)
  • typedef para um nome mais curto
  • Structs aninhadas e arrays de structs
💪 Não se preocupe se não entender de primeira
Structs em si são diretas; o operador -> só exige um bom entendimento de ponteiros.
Como revisar
  1. Comece com exemplos que usam só .
  2. Revise ponteiros e depois volte
  3. Lembre: p->x é abreviação de (*p).x
  4. Use typedef para encurtar os nomes
💡 Dica: Regra prática — use -> com ponteiros e . com objetos. Isso cobre 90% dos casos.

O que é uma struct?

Até agora, declaramos variáveis int, double e char uma de cada vez. Mas dados do mundo real geralmente vêm como um conjunto de valores relacionados — por exemplo, o nome, a idade e a altura de uma pessoa.
Uma struct permite agrupar variáveis de diferentes tipos em um único tipo novo.
Sem uma struct...
char name[20];
int age;
double height;
Se você adicionar outra pessoa, vai precisar de name1, name2, ... — a quantidade de variáveis explode.
Com uma struct
struct Person {
  char name[20];
  int age;
  double height;
};
Tudo fica empacotado em um único Person.

Definindo e Usando uma struct

Usar uma struct exige dois passos: (1) definir o tipo (o molde), depois (2) declarar uma variável (uma instância).
// (1) Define o tipo da struct (o molde)
struct Student {
  char name[20];
  int score;
};

// (2) Declare variáveis e use
struct Student s1;
strcpy(s1.name, "Tanaka");  // acesso com ponto (.)
s1.score = 85;

// Você também pode inicializar na declaração
struct Student s2 = {"Sato", 92};
Acesse membros com o operador ponto (.): s1.score significa "o campo score dentro de s1."

Layout de Memória da Struct

Os membros de uma struct são organizados na memória consecutivamente, na ordem de declaração.
Layout de memória de struct Student s1;
name[20] ocupa 20 bytes e score ocupa 4 bytes, então um Student usa no mínimo 24 bytes (o padding pode aumentar mais).

🧱 Visualização de Padding — a ordem dos membros afeta o tamanho

Para um acesso eficiente à memória, int precisa de alinhamento em 4 bytes e double em 8 bytes (alinhamento). O compilador insere padding entre os membros automaticamente. Só reordenar os membros pode reduzir o tamanho de uma struct.
🧪 Escolha um padrão
Escolha um padrão
// Nenhum padrão selecionado
Composição do tamanho
Dados reais: - B
Padding: - B
sizeof total: - B
※ Valores típicos em x86_64 Linux com gcc. Os resultados variam conforme a plataforma.
Layout em nível de byte (1 célula = 1 byte)
💡 Dica profissional: Para economizar memória (sistemas embarcados, grandes conjuntos de dados), declare os membros do maior para o menor (double → int → short → char). Para objetivos de localidade de cache, valem outras estratégias.

Arrays de Structs

Um array de structs permite gerenciar muitos registros que compartilham o mesmo formato. É aqui que as structs realmente brilham.
struct Student class[3] = {
  {"Tanaka", 85},
  {"Sato", 92},
  {"Suzuki", 78}
};

// Imprime a nota de cada aluno
for(int i = 0; i < 3; i++){
  printf("%s: %d pontos\n", class[i].name, class[i].score);
}
Combine o índice do array com o operador ponto, como em class[i].score. Lê-se naturalmente como "a nota do i-ésimo aluno."

Passando uma struct para uma Função

Structs podem ser passadas por valor (copiadas), mas copiar é caro para structs grandes, então passar um ponteiro é comum.
// Passagem por valor (a struct é copiada)
void printStudent(struct Student s){
  printf("%s: %d pontos\n", s.name, s.score);
}

// Passagem por ponteiro (refere-se ao original)
void addBonus(struct Student *sp, int bonus){
  sp->score += bonus; // equivalente a (*sp).score
}

addBonus(&s1, 5); // soma 5 pontos em s1.score
O operador de seta (->) é uma abreviação para acessar membros através de um ponteiro. sp->score é o mesmo que (*sp).score.

typedef — Dando um Apelido a um Tipo

typedef permite dar a um tipo um apelido mais claro. É especialmente útil com structs.

Uso básico

// Um apelido para unsigned int
typedef unsigned int uint;
uint score = 100;  // igual a unsigned int score = 100;

Structs e typedef (importante)

// Sem typedef — você precisa de "struct" toda vez
struct Point { int x, y; };
struct Point p1 = {3, 7};  // "struct" obrigatório

// Com typedef — você pode omitir "struct"
typedef struct { int x, y; } Point;
Point p1 = {3, 7};           // mais limpo
Na prática, structs com typedef são o padrão. O código fica mais curto e mais fácil de ler.

Enum (enum) — Um Grupo de Constantes Nomeadas

enum permite nomear e agrupar constantes inteiras relacionadas — ótimo para evitar números mágicos.
enum Color { RED, GREEN, BLUE };  // RED=0, GREEN=1, BLUE=2

enum Color c = GREEN;
printf("%d\n", c);  // 1

Especificando valores

enum Month {
    JAN = 1, FEB, MAR, APR, MAY, JUN,
    JUL, AUG, SEP, OCT, NOV, DEC
}; // FEB=2, MAR=3, ... DEC=12 (autoincrementado)

enum + switch

enum Direction { UP, DOWN, LEFT, RIGHT };

enum Direction dir = UP;
switch (dir) {
    case UP:    printf("Up\n");    break;
    case DOWN:  printf("Down\n");  break;
    case LEFT:  printf("Left\n");  break;
    case RIGHT: printf("Right\n"); break;
}
vs #define: Você poderia escrever #define RED 0 no lugar, mas um enum é tratado como um tipo, então o compilador pode ajudar com a verificação de tipos.
MétodoVerificação de tipoEscopoExibição no depurador
#define RED 0NenhumaArquivo inteiroApenas número
enum { RED }SimControlávelMostrado pelo nome

Experimente Você Mesmo — Structs

Guarde três alunos em um array de structs e calcule a média das notas.
struct.c
Saída
Clique em Executar...
💡 Mais ideias para testar
Publicidade

Aulas relacionadas

Avançado
Noções de Ponteiro
Entenda ponteiros em C com visualização de memória.
Laços, Arrays, Strings
Arrays
Declarando, inicializando e acessando arrays em C.
Avançado
E/S de Arquivos
fopen, fprintf, fscanf, fclose e como usá-los.
← Aula anterior
Aula 27: Noções de Ponteiro
Próxima aula →
Aula 29: E/S de Arquivos

Teste Rápido

Confira seu entendimento desta aula.

Q1. Qual operador acessa um membro de uma struct?

Apenas -> (seta)
Apenas . (ponto)
Ambos . e -> (dependendo do contexto)

Use . (ponto) para acessar diretamente a partir de uma variável, e -> (seta) para acessar através de um ponteiro.

Q2. O que acontece quando você passa uma struct para uma função?

É passada por referência
Uma cópia do valor é passada
É um erro de compilação

Em C, structs são passadas por valor (copiadas). Para structs grandes, passar um ponteiro é mais eficiente.

Q3. O que typedef struct faz?

Aloca a struct dinamicamente
Cria um apelido para o tipo da struct
Altera o tamanho da struct

typedef cria um apelido para um tipo, permitindo escrever Student s; em vez de struct Student s;.

Compartilhe este artigo
Compartilhar no X Compartilhar no Facebook