cglib

Is it correct to use GPtrArray for an array of strings (char*) in C?


I'm using GLib and C to make an application wherein I need to store a list of strings (i.e, a list of char*). Initially, I thought I would use GList or GArray, but then it hit me that strings just are pointers, so GPtrArray might be easiest to use, and so I used it. The only issue I encountered is that I have to cast the value back to a char* when accessing it via g_ptr_array_index as otherwise I just get a gpointer/void* back. Here is the error I get if I don't do the cast:

src/main.c:769:18: error: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘gpointer’ {aka ‘void *’} [-Werror=format=]
  769 |         printf("%s\n", g_ptr_array_index(setting_zero->key, 0));
      |                 ~^
      |                  |
      |                  char *
      |                 %p

However, it despite it feeling wrong to me (I'm not particularly experienced with writing C code), it seems to work just fine if I do add the cast.

As such, I ask, is it correct to use GPtrArray for storing an array of strings in C?


Solution

  • it hit me that strings just are pointers

    No, not exactly. C strings are arrays, or more precisely, a sequence of char ending with a null byte and stored in an array of char.

    Pointers are the way that most strings are referenced in C. They are not the strings themselves.

    As such, I ask, is it correct to use GPtrArray for storing an array of strings in C?

    GPtrArray represents an array of arbitrary object pointers. This is a good fit for pointers to strings.

    The only issue I encountered is that I have to cast the value back to a char* when accessing it via g_ptr_array_index as otherwise I just get a gpointer/void* back.

    You always get a gpointer back from g_ptr_array_index. Wherever you want a pointer of a different type, a conversion is required. To the extent that you can rely on gpointer to be an alias for void *, the required conversions will be performed automatically in most contexts, but those contexts do not include the variable arguments of a variadic function such as printf.

    The error you report is ordinarily a warning, so you must be compiling with -Werror or one of its variants (perhaps unbeknownst to you). The best solution is to insert the cast. There is no harm in this, and it does not say much about the suitability of GPtrArray for your purposes. The only way around would be to use a data structure specific to strings and type char *, so that there is no conversion to be performed in the first place.