C/C++ Arena

Step 4 of 10

calloc and strdup-style copies

calloc

calloc(count, size) allocates room for count elements of size bytes each, and sets every byte to zero. Use it when you want a clean starting state, like counters or a grid. Standard libraries also check that count * size doesn't overflow (returning NULL if it would), which malloc(count * size) can't do for you.

Copying a string onto the heap

A very common job: keep your own copy of a string, for example text that came from a temporary buffer. The recipe:

  1. Measure it with strlen.
  2. Allocate strlen(s) + 1 bytes. The +1 is for the '\0', and forgetting it is one of the most common bugs in C.
  3. Copy the characters, including the terminator (strcpy or memcpy with the +1).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *shout(const char *s) {
    size_t n = strlen(s);
    char *out = malloc(n + 2);
    if (out == NULL) {
        return NULL;
    }
    memcpy(out, s, n);
    out[n] = '!';
    out[n + 1] = '\0';
    return out;
}

int main(void) {
    char *msg = shout("hello");
    if (msg == NULL) {
        return 1;
    }
    printf("%s (%zu chars)\n", msg, strlen(msg));
    free(msg);
    int *counts = calloc(3, sizeof *counts);
    if (counts == NULL) {
        return 1;
    }
    printf("%d %d %d\n", counts[0], counts[1], counts[2]);
    free(counts);
    return 0;
}
hello! (6 chars)
0 0 0

shout needs n + 2 bytes: n characters, the !, and the terminator. Counting bytes carefully like this is everyday C.

(Many systems have strdup, which does steps 1 to 3 for you. It's standard since C23, but writing it yourself is good practice.)

Your turn: write char *copy_string(const char *s) that returns a new heap copy of s.

Previous: Return heap memory from a function Next: Growing with realloc