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.