How to return string from a function in C

Jul 05, 2023#c#cpp#how-to

To return a string in C, you need to understand that a string is an array of characters terminated by a null character (\0). You also need to be careful about memory allocation and deallocation, as well as the scope of the variables.

Here are some ways to declare a string in C:

char str1[20]; // declare a string of 20 characters
char str2[] = "Alice"; // initialize without size
char str3[6] = "Alice"; // initialize with size (include '\0')
char str4[] = {'A', 'l', 'i', 'c', 'e', '\0'}; // initialize without size
char str5[6] = {'A', 'l', 'i', 'c', 'e', '\0'}; // initialize with size
char *str6 = "Hello"; // pointer to a string literal
char *str7 = str2; // pointer to a string variable

There are different ways to return string from a function in C, but some of them are not recommended or have potential problems. Here are some common methods and their pros and cons:

Return a pointer to a local array

This is a bad idea. When you create a string within a function using a character array, the array is typically allocated on the stack. Once the function returns, the local variables, including the array, are deallocated, and accessing the returned pointer becomes undefined behavior.

char *myFunction ()  {
  char str[] = "my string";
  return str; // ❌ wrong!
}

Return a pointer to a static array

This is better than the previous method, because the static array will not be destroyed when the function exits, and the pointer will remain valid.

char *myFunction ()  {
  static char str[] = "my string";
  return str; // better, but not ideal
}

This method has some drawbacks, such as:

  • The static array can only be initialized once, and cannot be changed at runtime.
  • The static array has a fixed size, and may not be enough to hold the desired string.
  • The static array is shared by all calls to the function, and may cause unexpected side effects if modified by different callers.
  • The static array may not be thread-safe, and may cause concurrency issues if accessed by multiple threads.

Return a pointer to a dynamically allocated array

This is a more flexible method, because the dynamically allocated array can be initialized and changed at runtime, and can have any size as long as there is enough memory available.

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

char *myFunction ()  {
  char *array = malloc(10); // allocate memory for 10 characters
  if (array == NULL) return NULL; // check for allocation failure
  strcpy(array, "my string"); // copy the string to the array
  return array; // return the pointer
}

int main() {
  char *str = myFunction(); // call the function
  if (str == NULL) exit(1); // check for NULL pointer
  printf("%s\n", str); // print the string
  free(str); // free the memory
}

This method also has some drawbacks, such as:

  • The caller is responsible for freeing the memory allocated by the function, otherwise there will be memory leaks.
  • The caller needs to check if the function returns a valid pointer or NULL, in case of memory allocation failure.
  • The caller needs to know the length of the string returned by the function, or use functions like strlen or strcpy to manipulate it.

Pass a pointer to an array as an argument

This is another common method, where the caller provides an array as an argument to the function, and the function copies the string to that array.

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

int myFunction(char *array, int size) {
  char *str = "my string"; // the string to return
  int len = strlen(str); // get the length of the string
  if (len + 1 > size) return -1; // check if there is enough space in the array
  strcpy(array, str); // copy the string to the array
  return 0; // return success code
}

int main() {
  char buffer[10]; // declare an array of size 10
  int result = myFunction(buffer, 10); // call the function with the array and its size
  if (result == -1) exit(1); // check for error code
  printf("%s\n", buffer); // print the string
}

This method avoids memory allocation and deallocation issues, but also has some drawbacks, such as:

  • The caller needs to provide an array that is large enough to hold the string returned by the function, otherwise there will be buffer overflow errors.
  • The caller needs to pass the size of the array as another argument to the function, so that the function can check if there is enough space for the string.
  • The function needs to return an error code or a boolean value to indicate if the operation was successful or not.