0

I am given an array of strings in the form of a pointer to a pointer of a character (that is, char **). I wish to access each element in the array,

char **strings = {"hello", "bye", "whatusp"};

printf("%s\n", *(&strings));
printf("%s\n", *(&strings + 1));

I notice that the first printf() works, as it outputs "hello" for me, but the second doesn't output anything. The +1 does increment by 8 instead of 1, since the address is in bytes. How can I access an arbitrary element in such a double pointer?

Vincent Han
  • 1,373
  • 2
  • 8
  • 5
  • Compiler won't be able to interpret this `char **strings = {"hello", "bye", "whatusp"};` – जलजनक Feb 26 '22 at 01:19
  • You can't do it statically, you will have to use `malloc`, at least for the first dimension. – alex01011 Feb 26 '22 at 01:33
  • This should cause a compiler error (and does for me). The only was to do this directly is to create `strings` as a 2D arrar: `char strings[3][8] = { "Hello", "Bye", "Whatusp" };` – SGeorgiades Feb 26 '22 at 02:04

4 Answers4

1

Just as simple as:

char *strings[] = {"hello", "bye", "whatusp"};

printf("%s\n", strings[0]);
printf("%s\n", strings[1]);
printf("%s\n", strings[2]);
जलजनक
  • 3,072
  • 2
  • 24
  • 30
1

First of all, the line

char **strings = {"hello", "bye", "whatusp"};

is wrong. If you want to declare an array of 3 pointers to string literals, then it should be the following instead:

char *strings[3] = {"hello", "bye", "whatusp"};

In the previous line, you can omit the 3, because the compiler is smart enough to count the number of elements itself, since you are initializing the array.

The lines

printf("%s\n", *(&strings));
printf("%s\n", *(&strings + 1));

are also wrong, because when using printf with the %s format specifier, you must provide a pointer to a string, i.e. a char *. However, you are providing a char** instead in both lines.

The expression *(&strings) will evaluate to a char ** for the following reason:

The expression &strings will evaluate to a pointer to strings. Since strings itself is an array of 3 pointers to char, a pointer to strings is a pointer to an array of 3 pointers to char. Afterwards, you are applying the indirection operator * on this data type, so that the result of this operation is an array of 3 pointers to char. When passing this data type to printf, the array will decay to a pointer to the first element of the array, i.e. to a pointer to a pointer to a char (which is a char**).

You should simply write the following instead:

printf( "%s\n", strings[0] );
printf( "%s\n", strings[1] );

The expression strings[1] is equivalent to *(strings+1).

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
0

char **strings is a pointer to a pointer to char, not array of pointers to char, your compiler should have given you a warning anyways, if not you should enable them.

For that assignment to work, you will need to have an array of pointers, char *strings[] or if you want to use plain pointer notation (array notation is using pointer arithmetic in the background though), you could dynamically allocate memory for the first dimension.

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

#define SIZE 3

int main(void)
{
   char **strs = NULL;

   if ((strs = malloc(SIZE * sizeof(char *))) == NULL) /* check malloc result */
   {
      exit(EXIT_FAILURE);
   }

  *strs       = "hello"; /* assignment makes sense in this case but you cant modify the string since its read-only*/
  *(strs + 1) = "bye";
  *(strs + 2) = "whatsup";

   for (int i = 0; i < SIZE; i++)
   {
      puts(*(strs + i));
   }

   /* Alternative that will allocate space for each string if you need to store them or modify them later */

    /*  for (int i = 0; i < 3; i++)
   {
      if ((*(strs + i) = malloc(YOUR_STRINGS_LENGTH)) == NULL)
      {
         exit(EXIT_FAILURE);
      }
      
      snprintf(*(strs + i), YOUR_STRINGS_LENGTH, "string");

   }
   */

  return 0;
}
alex01011
  • 1,670
  • 2
  • 5
  • 17
0

I am given an array of strings in the form of a pointer to a pointer of a character (that is, char **)

There is no such thing: a char** is just a pointer. It is not an array. if thing is char** then
*thing is char* and **thing is, as declared, a char.

An array can be seen as a pointer, but a pointer is not an array.

note: the prototype for main is in general

    int main( int argc, char** argv)

so what you need to do is the same as every C program gets from the system.

Example

To have char** as an array of pointers to char you must build it

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

int main(int argc, char** argv)
{
    char* array[] = {
    "I", "wish", "to", "access", "each", "element",
    "in", "the", "array"
    };

    int N = sizeof(array) / sizeof(char*);
    printf("%d strings in total\n\n", N);

    char** strings = (char**)malloc(N * sizeof(char*));
    for (int i = 0; i < N; i=i+1)
        *(strings+i) = *(array + i);

    for (int i = 0; i < N; i=i+1) 
        printf("%3d  %s\n", 1 + i, *(i + strings));

    // pointer is not an array
    char thing = '@';
    char* p = &thing;
    char** pp = &p;

    printf("\n\nthing is '%c', *p is '%c', **pp is '%c'\n",
        thing, *p, **pp);

    return 0;
}

output

9 strings in total

  1  I
  2  wish
  3  to
  4  access
  5  each
  6  element
  7  in
  8  the
  9  array


thing is '@', *p is '@', **pp is '@'

In particular note this lines

char** strings = (char**)malloc(N * sizeof(char*));
    for (int i = 0; i < N; i=i+1)
        *(strings+i) = *(array + i);

where is defined that strings is an area of the needed size and than the pointers are initialized to the strings of the input array.

arfneto
  • 1,227
  • 1
  • 6
  • 13