Aulas de C para quem já sabe Python

Aprendendo C depois de aprender Python

006 - Ponteiros e alocação dinâmica

Arquivos necessários

Baixe todos os programas aqui.

Configuração do VSCode

Idênticas as da aula 5, incluídas no zip desta aula.

C

ponteiro1.c

#include <stdio.h>

int main(void)
{
    char a = 'C';
    char *p = nullptr;

    printf("a contém %c\n", a);
    printf("p contém %p\n", p);
    printf("&a é %p\n", (void *)&a);
    printf("&p é %p\n", (void *)&p);
    puts("\np recebe o endereço de a\n");

    p = &a;
    printf("p contém %p\n", p);
    printf("&p é %p\n", (void *)&p);
    printf("a contém %c\n", a);
    printf("*p é %c\n", *p);

    puts("\np altera o conteúdo de a\n");
    *p = 'D';
    printf("p contém %p\n", p);
    printf("&p é %p\n", (void *)&p);
    printf("a contém %c\n", a);
    printf("*p é %c\n", *p);
}

ponteiro2.c

#include <stdio.h>

void troca_sp(int a, int b)
{
    int tmp = a;
    a = b;
    b = tmp;
}


void troca(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int main(void)
{
    int a = 5, b = 3;
    printf("a=%d b=%d\n", a, b);
    // Por valor
    troca_sp(a, b);
    printf("a=%d b=%d\n", a, b);
    // Por referencia
    troca(&a, &b);
    printf("a=%d b=%d\n", a, b);
}

alocando1.c

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    char *s = nullptr;

    printf("s antes da alocação: %p\n", s);

    s = malloc(50);
    printf("s depois da alocação: %p\n", s);
    free(s);
}

alocando2.c

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    int nelementos = 0;
    puts("Digite o número de elementos:");
    scanf("%d", &nelementos);

    int *a = malloc(sizeof(int) * nelementos);
    for (int i = 0; i < nelementos; i++)
    {
        // *(a + i) = i * 2;
        a[i] = i * 2;
    }
    for (int i = 0; i < nelementos; i++)
    {
        printf("[%d] = %d\n", i, a[i]);
    }
    free(a);
}

alocando3.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char *replica(char modelo, int quantidade)
{
    char *s = malloc(quantidade + 1);
    memset(s, modelo, quantidade);
    s[quantidade] = 0;
    return s;
}

int main(void)
{
    char *s = nullptr;
    for (int i = 1; i < 20; i++)
    {
        s = replica('.', i);
        printf("[%s]\n", s);
        free(s);
    }
}

alocando4.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void replica(char **z, char modelo, int quantidade)
{
    *z = malloc(quantidade + 1);
    memset(*z, modelo, quantidade);
    (*z)[quantidade] = 0;
}

int main(void)
{
    char *s = nullptr;
    for (int i = 1; i < 10; i++)
    {
        replica(&s, '=', i);
        printf("[%s]\n", s);
        free(s);
    }
}

struct1.c

#include <stdio.h>
#include <stdlib.h>

struct exemplo
{
    int a;
    int b;
};

void print_struct(char *nome, struct exemplo v)
{
    printf("%s {a=%d, b=%d}\n", nome, v.a, v.b);
}

int main(void)
{
    struct exemplo x1, x2 = {.a = 1, .b = 2};
    x1.a = 10;
    x1.b = 20;
    print_struct("x1", x1);
    print_struct("x2", x2);
    x2.a = 5;
    print_struct("x2", x2);
}

struct2.c

#include <stdio.h>
#include <stdlib.h>

typedef struct exemplo
{
    int a;
    int b;
} exemplo;

void print_struct(char *nome, exemplo v)
{
    printf("%s {a=%d, b=%d}\n", nome, v.a, v.b);
}

int main(void)
{
    exemplo x1, x2 = {.a = 1, .b = 2};
    x1.a = 10;
    x1.b = 20;
    print_struct("x1", x1);
    print_struct("x2", x2);
}

struct3.c

#include <stdio.h>
#include <stdlib.h>

typedef struct exemplo
{
    int a;
    int b;
} exemplo;

void print_struct(char *nome, exemplo v)
{
    printf("%s {a=%d, b=%d}\n", nome, v.a, v.b);
}

void troca_a_b(exemplo v)
{
    int tmp = v.a;
    v.a = v.b;
    v.b = tmp;
}

int main(void)
{
    exemplo x1 = {.a = 1, .b = 2};
    print_struct("x1", x1);
    troca_a_b(x1);
    print_struct("x1", x1);
}

struct4.c

#include <stdio.h>
#include <stdlib.h>

typedef struct exemplo
{
    int a;
    int b;
} exemplo;

void print_struct(char *nome, exemplo v)
{
    printf("%s {a=%d, b=%d}\n", nome, v.a, v.b);
}

void troca_a_b(exemplo *v)
{
    int tmp = v->a;
    v->a = v->b;
    v->b = tmp;
}

int main(void)
{
    exemplo x1 = {.a = 1, .b = 2};
    print_struct("x1", x1);
    troca_a_b(&x1);
    print_struct("x1", x1);
}

struct5.c

#include <stdio.h>
#include <stdlib.h>

typedef struct exemplo
{
    int a;
    int b;
} exemplo;

void print_struct(char *nome, exemplo v)
{
    printf("%s {a=%d, b=%d}\n", nome, v.a, v.b);
}

exemplo *cria(int a, int b)
{
    exemplo *nova = malloc(sizeof(exemplo));
    nova->a = a;
    nova->b = b;
    return nova;
}

int main(void)
{
    const int N = 10;
    exemplo *x[N];
    for (int i = 0; i < N; i++)
    {
        x[i] = cria(i, i * 2);
    }
    for (int i = 0; i < N; i++)
    {
        printf("i=%d x[%d]=%p ", i, i, (void *)x[i]);
        print_struct("x", *x[i]);
    }
    for (int i = 0; i < N; i++)
    {
        free(x[i]);
    }
}

struct6.c

#include <stdio.h>
#include <stdlib.h>

typedef struct exemplo
{
    int a;
    int b;
} exemplo;

void print_struct(char *nome, exemplo v)
{
    printf("%s {a=%d, b=%d}\n", nome, v.a, v.b);
}

int main(void)
{
    const int N = 10;
    exemplo *x = malloc(sizeof(exemplo) * N);
    for (int i = 0; i < N; i++)
    {
        x[i] = (exemplo){.a = i, .b = 2 * i};
    }
    for (int i = 0; i < N; i++)
    {
        printf("i=%d x[%d]=%p ", i, i, (void *)&x[i]);
        print_struct("x", x[i]);
    }
    puts("\nCom aritmética de ponteiros:");
    for (int i = 0; i < N; i++)
    {
        printf("i=%d x[%d]=%p ", i, i, (void *)(x + i));
        print_struct("x", x[i]);
    }
    free(x);
}

lista1.c

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct exemplo
{
    int a;
    int b;
} exemplo;

typedef struct lista
{
    int tamanho;
    int capacidade;
    exemplo *elementos;
} lista;

lista *cria_lista(int capacidade)
{
    lista *nova_lista = malloc(sizeof(lista));
    *nova_lista = (lista){.tamanho = 0,
                          .capacidade = capacidade,
                          .elementos = malloc(sizeof(exemplo) * capacidade)};
    return nova_lista;
}

bool append(lista *l, exemplo valor)
{
    if (l->tamanho == l->capacidade)
    {
        return false;
    }
    l->elementos[l->tamanho] = valor;
    l->tamanho += 1;
    return true;
}

void print_struct(char *nome, exemplo v)
{
    printf("%s {a=%d, b=%d}\n", nome, v.a, v.b);
}

int main(void)
{
    lista *l = cria_lista(10);
    for (int i = 0; i < 10; i++)
    {
        if (!append(l, (exemplo){.a = i, .b = i * 3}))
        {
            printf("Erro, não consegui adicionar o elemento %d\n", i);
        }
    }
    for (int v = 0; v < l->tamanho; v++)
    {
        char etiqueta[50];
        sprintf(etiqueta, "l[%d]", v);
        print_struct(etiqueta, l->elementos[v]);
    }
    // free(l->elementos);
    free(l);
}

lista2.c

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct exemplo
{
    int a;
    int b;
} exemplo;

typedef struct lista
{
    int tamanho;
    int capacidade;
    exemplo *elementos;
} lista;

lista *cria_lista(int capacidade)
{
    lista *nova_lista = malloc(sizeof(lista));
    *nova_lista = (lista){.tamanho = 0,
                          .capacidade = capacidade,
                          .elementos = malloc(sizeof(exemplo) * capacidade)};
    return nova_lista;
}

bool append(lista *l, exemplo valor)
{
    if (l->tamanho == l->capacidade)
    {
        return false;
    }
    l->elementos[l->tamanho] = valor;
    l->tamanho += 1;
    return true;
}

void libera_lista(lista *l)
{
    l->tamanho = 0;
    l->capacidade = 0;
    free(l->elementos);
    free(l);
}

void print_struct(char *nome, exemplo v)
{
    printf("%s {a=%d, b=%d}\n", nome, v.a, v.b);
}

int main(void)
{
    lista *l = cria_lista(10);
    for (int i = 0; i < 10; i++)
    {
        if (!append(l, (exemplo){.a = i, .b = i * 3}))
        {
            printf("Erro, não consegui adicionar o elemento %d", i);
        }
    }
    for (int v = 0; v < l->tamanho; v++)
    {
        char etiqueta[50];
        sprintf(etiqueta, "l[%d]", v);
        print_struct(etiqueta, l->elementos[v]);
    }
    libera_lista(l);
}

lista3.c

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct exemplo
{
    int a;
    int b;
} exemplo;

typedef struct lista
{
    int tamanho;
    int capacidade;
    exemplo **elementos;
} lista;

lista *cria_lista(int capacidade)
{
    lista *nova_lista = malloc(sizeof(lista));
    *nova_lista = (lista){.tamanho = 0,
                          .capacidade = capacidade,
                          .elementos = malloc(sizeof(exemplo *) * capacidade)};
    return nova_lista;
}

bool append(lista *l, exemplo valor)
{
    if (l->tamanho == l->capacidade)
    {
        return false;
    }
    exemplo *novo = malloc(sizeof(exemplo));
    l->elementos[l->tamanho] = novo;
    *novo = valor;
    l->tamanho += 1;
    return true;
}

void libera_lista(lista *l)
{
    for (int x = 0; x < l->tamanho; x++)
    {
        free(l->elementos[x]);
    }
    l->tamanho = 0;
    l->capacidade = 0;
    free(l->elementos);
    free(l);
}

void print_struct(char *nome, exemplo v)
{
    printf("%s {a=%d, b=%d}\n", nome, v.a, v.b);
}

int main(void)
{
    const int MAX = 25;
    lista *l = cria_lista(MAX);
    for (int i = 0; i < MAX; i++)
    {
        if (!append(l, (exemplo){.a = i, .b = i * 3}))
        {
            printf("Erro, não consegui adicionar o elemento %d\n", i);
        }
    }
    char etiqueta[50];
    for (int v = 0; v < l->tamanho; v++)
    {        
        sprintf(etiqueta, "l[%d]", v);
        print_struct(etiqueta, *l->elementos[v]);
    }
    libera_lista(l);
}

realloc1.c

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    char *p = nullptr;
    printf("p aponta para %p\n", p);
    p = malloc(100);
    printf("p aponta para %p (após malloc)\n", p);
    p = realloc(p, 200);
    printf("p aponta para %p (após realloc)\n", p);
    free(p);
}

realloc2.c

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// Modificação de lista 3

typedef struct exemplo
{
    int a;
    int b;
} exemplo;

typedef struct lista
{
    int tamanho;
    int capacidade;
    exemplo **elementos;
} lista;

lista *cria_lista(int capacidade)
{
    lista *nova_lista = malloc(sizeof(lista));
    *nova_lista = (lista){.tamanho = 0,
                          .capacidade = capacidade,
                          .elementos = malloc(sizeof(exemplo *) * capacidade)};
    return nova_lista;
}

bool append(lista *l, exemplo valor)
{
    if (l->tamanho == l->capacidade)
    {
        printf("Expandindo... dobrando a capacidade (%d -> %d).\n", l->capacidade, l->capacidade * 2);
        exemplo **novo = realloc(l->elementos, (l->capacidade * 2) * sizeof(exemplo *));
        if (novo != nullptr)
        {
            l->elementos = novo;
            l->capacidade *= 2;
        }
        else
        {
            return false;
        }
    }
    exemplo *novo = malloc(sizeof(exemplo));
    l->elementos[l->tamanho] = novo;
    *novo = valor;
    l->tamanho += 1;
    return true;
}

void libera_lista(lista *l)
{
    for (int x = 0; x < l->tamanho; x++)
    {
        free(l->elementos[x]);
    }
    l->tamanho = 0;
    l->capacidade = 0;
    free(l->elementos);
    free(l);
}

void print_struct(char *nome, exemplo v)
{
    printf("%s {a=%d, b=%d}\n", nome, v.a, v.b);
}

int main(void)
{
    lista *l = cria_lista(10);
    for (int i = 0; i < 1000; i++)
    {
        if (!append(l, (exemplo){.a = i, .b = i * 3}))
        {
            printf("Erro, não consegui adicionar o elemento %d\n", i);
        }
    }
    char etiqueta[50];
    for (int v = 0; v < l->tamanho; v++)
    {
        sprintf(etiqueta, "l[%d]", v);
        print_struct(etiqueta, *l->elementos[v]);
        //printf("Endereco de %s > %p\n", etiqueta, (void *) l->elementos[v]);
    }
    libera_lista(l);
}

calloc1.c

#include <stdlib.h>
#include <stdio.h>


int main(void){
    int *v = malloc(10 * sizeof(int));
    int *c = calloc(10, sizeof(int));
    printf("v=%p\n", (void *)v);
    printf("c=%p\n", (void *)c);
    free(v);
    free(c);
}

void.c

#include <stdio.h>

#ifdef _WIN32
#include <winsock.h>
#else
#include <arpa/inet.h>
#endif

int main(void)
{
    int z = 10;
    double zd = z;
    printf("%d - %f\n", z, zd);

    int x = 3;
    double zdx = z / x;
    printf("%f\n", zdx);

    double zdy = z / (double)x;
    printf("%f\n", zdy);

    void *a = (void *)0xdeadbeef;
    printf("a = %p\n", a);
    printf("a = %zu\n", sizeof(a));
    // a += 1;
    int b = 0xadacaffe;
    a = &b;
    printf("a = %p\n", a);
    // printf("a = %d\n", *a);
    char *c = a;
    printf("c[0] = %02x\n", *c);
    printf("c[1] = %02x\n", *(c + 1));
    printf("c[2] = %02x\n", *(c + 2));
    printf("c[3] = %02x\n\n", *(c + 3));

    unsigned char *uc = a;
    printf("uc[0] = %02x\n", *uc);
    printf("uc[1] = %02x\n", *(uc + 1));
    printf("uc[2] = %02x\n", *(uc + 2));
    printf("uc[3] = %02x\n", *(uc + 3));
    printf("%02x %02x %02x %02x\n", uc[0], uc[1], uc[2], uc[3]);

    int n = htonl(b);
    unsigned char *ucn = (unsigned char *)&n;
    printf("ucn[0] = %02x\n", *ucn);
    printf("ucn[1] = %02x\n", *(ucn + 1));
    printf("ucn[2] = %02x\n", *(ucn + 2));
    printf("ucn[3] = %02x\n", *(ucn + 3));
    printf("%02x %02x %02x %02x\n", ucn[0], ucn[1], ucn[2], ucn[3]);
}

func.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int soma(int a, int b)
{
    return a + b;
}

int sub(int a, int b)
{
    return a - b;
}

char *nova(int x)
{
    char *n = malloc(x + 1);
    memset(n, 'x', x);
    n[x] = 0;
    return n;
}

int main(void)
{
    int (*p)(int, int) = soma;
    printf("p é soma(1, 2): %d\n", p(1, 2));
    p = sub;
    printf("p é sub(5, 3): %d\n", p(5, 3));
    char *(*z)(int) = nova;
    for (int nz = 1; nz < 10; nz++)
    {
        char *r = z(nz);
        printf("z(%d) => %s\n", nz, r);
        free(r);
    }
}

Videos

Linguagem C para quem já programa em Python - Aula 6

Parte 1 - Conceito de ponteiro, endereço, passagem por valor e por referência

Parte 2 - Alocação dinâmica, malloc, free, memset, ponteiros para ponteiros

Parte 3 - Estruturas (structs)

Parte 4 - listas, sprintf e realloc

Disponível a partir de 29/05/2024 (19:00 Bruxelas)

Parte 5 - calloc, void pointer, pre-processador, ponteiros para funções

Disponível a partir de 01/06/2024 (19:00 Bruxelas)

Assine o canal para não perder os novos vídeos

https://www.youtube.com/channel/UCLwVwuuS7VpVOGF-SAJp_JQ