Home > Mobile >  How to access different elements in char** in C?
How to access different elements in char** in C?

Time:02-26

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?

CodePudding user response:

Just as simple as:

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

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

CodePudding user response:

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).

CodePudding user response:

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;
}

CodePudding user response:

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("=  %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.

  • Related