When Passing a String to a Function, Be Careful That You Don’t . . .

Passing a string to a function? Check!
Passing an array of strings to a function? Watch out!

From last week’s Lesson, I’m attempting to pass an array of strings to a function, one at a time. Within the function, the string’s characters are modified. The modified string is output from the main() function.

My original code blew up. The strings are passed to the function just fine, but once the string’s characters are modified, BOOM.

I kept working and working the function, looking in a debugger, and getting cross with my cats. Nothing helped.

Then I looked at the string definition:

char *strings[3] = {
    "Hello, world!",
    "This is a string test",
    "Once upon a time, there was a string"

May the gods forgive me.

This declaration commits the sin of declaring a string as a pointer. You can do it, but lord help you if you attempt to modify the string. I’ve even written about this topic before! How stupid can I be?

You want to be extremely careful when you declare a string literal as a pointer: individually or in an array. If the strings aren’t to be modified, fine. Declare them as const types. No problem.

If you choose to modify the strings, just don’t initialize the array of pointers. This way, you can pass the string pointer to a function and manipulate it. To avoid the mistake, the strings must be initialized elsewhere, then their addresses assigned to the char pointer array.

For example, you start like this:

char *strings[3];

This array is declared as storage for three char pointers, which eventually will reference strings. Observe that this declaration doesn’t assign anything to the array; it’s just storage. The strings to manipulate, and eventually reference in the strings[] array, are declared on their own:

char a[] = "Hello, world!";
char b[] = "This is a string test";
char c[] = "Once upon a time, there was a string";

These strings are char arrays, not pointers. The array name serves as the base address for each string, like a pointer. In fact, the next step is to reference each array as an element within the strings[] pointer array:

strings[0] = a;
strings[1] = b;
strings[2] = c;

These statements copy the address of each string into the string[] array’s elements. That’s it. The char pointer array is now initialized properly. The strings referenced in the array can be sent to a function for direct manipulation, as this modification to my earlier code demonstrates:

2021_09_04-Lesson.c

#include <stdio.h>

void increase(char *a)
{
    while(*a)
    {
        *a = *a + 1;
        a++;
    }
}

int main()
{
    char *strings[3];
    char a[] = "Hello, world!";
    char b[] = "This is a string test";
    char c[] = "Once upon a time, there was a string";
    int x;

    /* allocate pointers */
    strings[0] = a;
    strings[1] = b;
    strings[2] = c;

    /* copy the strings */

    for( x=0; x<3; x++ )
    {
        printf("%s = ",strings[x]);
        increase(strings[x]);
        printf("%s\n",strings[x]);
    }

    return(0);
}

The program now works, with no excess choking taking place in the increase() function:

Hello, world! = Ifmmp-!xpsme"
This is a string test = Uijt!jt!b!tusjoh!uftu
Once upon a time, there was a string = Podf!vqpo!b!ujnf-!uifsf!xbt!b!tusjoh

What I’ve learned from this episode is, first, always remember those things I tell others never to forget: The direct pointer-string assignment is fine for referencing strings, but such strings cannot be modified!

Second, I learned that if you do want to modify strings in an array, assign the string values separately. May I never forget that.

Leave a Reply