Sometimes you point to null in C/C++

Posted in software by Christopher R. Wirz on Mon Jan 11 2016



In low level languages like C and C++, strings can be represented by arrays of characters. This takes the appearance of char[] or char*, but with one small difference. It is implied that all string character arrays end with a terminator '\0'.

The following expressions are nearly the same:

char* str = "Modified"; // The pointer is to the first element
char str[] = "Modified";
char str[9] = "Modified";
char str[] = {'M','o','d','i','f','i','e','d','\0'};
char str[9] = {'M','o','d','i','f','i','e','d','\0'};

So what if you want to change or initialize a string array's value. There are a few options. One would assume you have to pass it in to a method using char[] or char*.

void method(char* val){
    // set the value
}

This is probably the most tricky because you are going to have to know the length of the string.

You can try using char** or char*& which reference the character array.

void method(char** val){
    // set the value
}

Or this, which is only available in C++.

void method(char*& val){
    // set the value
}

Another advantage of the last two is that you don't have to provide an initial value for char* val. Let's see how we would write and run each of these:


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

// This will accomplish nothing
void set_char_pointer(char* val){
    val = (char*)"Modified string";
}

// This will sprintf over the char*
void sprintf_char_pointer(char* val){
    // can only be as long as previous value
    sprintf(val, "Modified");
}

// In this case, val doesn't even have to be initialized
void char_pointer_pointer(char** val) {
    *val = "Modified";
}

#ifdef __cplusplus
// This trick will work in c++, but not in c
void char_pointer_ref(char*& val) {
    val = "Modified";
}
#endif

int main()
{
    char * orig = "Original";
    set_char_pointer(orig);
    printf("set_char_pointer(char* val) => \"%s\"\n", orig);

    // char* orig1 = "Original"; // produces an error in this case
    char orig1[9] = "Original";
    sprintf_char_pointer(orig1);
    printf("sprintf_char_pointer(char* val) => \"%s\"\n", orig1);

    char * orig2 = NULL; // Doesn't have to be initialized
    char_pointer_pointer(&orig2);
    printf("char_pointer_pointer(char** val) => \"%s\"\n", orig2);

    #ifdef __cplusplus
    char * orig3 = NULL; // Doesn't have to be initialized
    char_pointer_ref(orig3);
    printf("char_pointer_ref(char*& val) => \"%s\"\n", orig3);
    #endif
    return 0;
}

This outputs the following results:


set_char_pointer(char* val) => "Original"
sprintf_char_pointer(char* val) => "Modified"
char_pointer_pointer(char** val) => "Modified"
char_pointer_ref(char*& val) => "Modified"

For setting the value of a new string array, it seems like char_pointer_pointer(char** val) makes the most sense. You don't have to allocate or initialize the string array and it is available in C and C++. This seems like one of those times where setting a pointer to NULL doesn't cause any trouble.

Now go ahead and try this on your own.