LeetCode 1108: Defanging an IP Address I'm posting two solutions for LeetCode's &quot;Defanging an IP Address&quot;. If you'd like to review, please do. Thank you!
Problem
Given a valid (IPv4) IP address, return a defanged version of that IP address.
A defanged IP address replaces every period &quot;.&quot; with &quot;[.]&quot;.
Example 1:
Input: address = &quot;1.1.1.1&quot;
Output: &quot;1[.]1[.]1[.]1&quot;

Example 2:
Input: address = &quot;255.100.50.0&quot;
Output: &quot;255[.]100[.]50[.]0&quot;

Constraints:

The given address is a valid IPv4 address.

Code 1
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

static const char* defangIPaddr(
    char* address
) {
    char* ipv4_memory = calloc(1, sizeof(&quot;###[.]###[.]###[.]###&quot;));
    char* defanged = ipv4_memory;

    for (char* character = address; *character; character++) {
        if (*character == '.') {
            *ipv4_memory++ = '[';
            *ipv4_memory++ = '.';
            *ipv4_memory++ = ']';

        } else {
            *ipv4_memory++ = *character;
        }
    }

    return defanged;
}


int main() {

    printf (&quot;%s \n&quot;, defangIPaddr(&quot;1.1.1.1&quot;));
    printf (&quot;%s \n&quot;, defangIPaddr(&quot;255.100.50.0&quot;));

    return 0;
}

Code 2 without changing the input:
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

static const char* defangIPaddr(
    const char* address
) {
    char* cloned_address = NULL;
    cloned_address = strdup(address);

    char* ipv4_memory = calloc(1, sizeof(&quot;###[.]###[.]###[.]###&quot;));
    char* defanged = ipv4_memory;


    for (char* character = cloned_address; *character; character++) {
        if (*character == '.') {
            *ipv4_memory++ = '[';
            *ipv4_memory++ = '.';
            *ipv4_memory++ = ']';

        } else {
            *ipv4_memory++ = *character;
        }
    }

    return defanged;
}


int main() {

    printf (&quot;%s \n&quot;, defangIPaddr(&quot;1.1.1.1&quot;));
    printf (&quot;%s \n&quot;, defangIPaddr(&quot;255.100.50.0&quot;));

    return 0;
}
Watch your memory allocations and deallocations. In both cases, you've got defangIPaddr returning a const char * to heap-allocated memory, which needs to be freed by the caller... but it can't be freed, because free expects a non-const void* as its argument.
Functions that return ownership-of-a-heap-allocation to the caller should (A) return char*, not const char*, and (B) be clearly documented.
In Code 2, you're not just leaking the returned pointer; you're also leaking the strdup'ed original pointer. There's no reason to call strdup here.
What you want is simply
char *defangIPaddr(const char *address) {
    char *defanged = calloc(sizeof(&quot;###[.]###[.]###[.]###&quot;), 1);
    char *q = defanged;
    for (const char *p = address; *p != '\0'; ++p) {
        if (*p == '.') {
            *q++ = '[';
            *q++ = '.';
            *q++ = ']';
        } else {
            *q++ = *p;
        }
    }
    return defanged;
}

I've shortened your names character and ipv4_memory to just p and q. My p is for &quot;pointer&quot;; it's not a character at all, so character is a misleading name for it. q is simply what comes after p.
You got the arguments to calloc in the wrong order. In practice this doesn't matter; but getting it correct is easy and free. If you're unsure about an interface, check the man page.
In your original code, you did this:
char* cloned_address = NULL;
cloned_address = strdup(address);

That's a verbose way of writing
char* cloned_address = strdup(address);

Always initialize your variables — but initialize them to the right values! Don't initialize to a nonsense or garbage value and then later assign the right value over it; just initialize with the right value to begin with.

sizeof(&quot;###[.]###[.]###[.]###&quot;) is a mildly sneaky way of computing the maximum possible length. It might be better to allocate simply 3*strlen(address)+1 bytes, so that you can't possibly buffer-overflow, even if the caller passes in &quot;..................&quot; as their input.
Alternatively, you could compute the exact right buffer length and malloc exactly that much.
    int len = 0;
    for (const char *p = address; *p != '\0'; ++p) {
        len += (*p == '.') ? 3 : 1;
    }
    char *defanged = calloc(len+1, 1);
    [...]


Consider throwing in an if (defanged == NULL) return NULL; just in case the allocation fails.