Marcelo Araujo
Marcelo Araujo

Reputation: 145

char **s versus char *s[], when and how to use each one?

If I use char *s[], I can do the following:

char *s[] = {"foo", "bar", "foobar", "whatever", "john", "doe"};

What is the difference with **s? How do I use the char **s instead of char *s[] in that case?

Example: int main (int argc, char **argv) instead of *argv[]

Upvotes: 6

Views: 5062

Answers (9)

Anders Abel
Anders Abel

Reputation: 69250

Arrays and pointers are different things. A pointer can be used to access an element in the array. To be able to initialize an array, you need to declare an array, not a pointer.

To show clearly the difference try this:

int[] ia = {1, 2, 3, 4, 5, 6, 7, 8};
int* ip = ia;

printf("sizeof(ia): %zu, sizeof(ip): %zu", sizeof(ia), sizeof(ip));

The first should print the size of the array, the second the size of an int pointer.

The odd thing with C is that when an array is passed as a parameter to a function it decays into a pointer. See more in section 2.3 of http://www.lysator.liu.se/c/c-faq/c-2.html. The reason main accepts argv** instead of argv*[] is that argv*[] is decayed into argv** when passed as a function parameter.

Upvotes: 1

Santhosh
Santhosh

Reputation: 901

It depends upon your requirement. If your program doesn't have to modify these strings later you can use

char *s[] = {"foo", "bar", "foobar", "whatever", "john", "doe"};

These are compiled as string literals in read only section.

Assembly output:

        .file   "test.c"
        .section        .rodata
.LC0:
        .string "foo"
.LC1:
        .string "bar"
.LC2:
        .string "foobar"
.LC3:
        .string "whatever"
.LC4:
        .string "john"
.LC5:
        .string "doe"
        .text

If you try to modify these strings later in the program you would get a segmentation fault. In that case you have to use char **s

Upvotes: 0

hari
hari

Reputation: 9733

Not direct answer to your que but this might help you understand a bit more:

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

int main() {

    char *s[] = {"foo", "bar", "foobar", "whatever", "john", "doe"};

    printf("  s[0]: %s \n", s[0]);
    printf("    *s: %s \n", *s);
    printf("  *s+1: %s \n", *s+1);
    printf("*(s+1): %s \n", *(s+1));

return 0;
}

Output:

$ gcc -o chararr chararr.c 
$ ./chararr 
  s[0]: foo   
    *s: foo 
  *s+1: oo 
*(s+1): bar 

Upvotes: 1

Armen Tsirunyan
Armen Tsirunyan

Reputation: 132974

As function parameters, there is no difference whatsoever. They are equivalent.

void f(int** p);
void f(int* p[]);
void f(int* p[42]);

These three declarations are equivalent.

As objects, they have different types;

char *s[] = {"foo", "bar", "foobar", "whatever", "john, "doe"};

s is an array of 6 pointers to char sizeof(s) == 6*sizeof(void*)

char **s;

s is a pointer to pointer to char. sizeof(s) == sizeof(void*)

Upvotes: 4

Soumen
Soumen

Reputation: 1036

when you use char *s[] = {"foo", "bar", "foobar", "whatever", "john, "doe"}; the compiler already knows the length of array ie: in this case it knows the its a pointer to pointers of 6 character arrays.

char** lacks the length information and thats specifically why main has 2 arguments {length, pointer to pointer to char} == {argc, arv}

Upvotes: 0

Paul
Paul

Reputation: 141819

They create the same data structure. The only difference s that char*s[] automatically mallocates enough memory for {"foo", "bar", "foobar", "whatever", "john, "doe"} upon initialization. char **s would only allocate one byte for the pointer then you'd to manually mallocate memory yourself for the each string in the array.

Upvotes: 1

Emil Condrea
Emil Condrea

Reputation: 9963

If you define

char **s[] = {"foo", "bar", "foobar", "whatever", "john, "doe"};

I think that it's the same like defining tridiensional arrays (char s[10][10][10]), since char *s[] is defining a bidimensional array.

Upvotes: 0

sidyll
sidyll

Reputation: 59277

For function parameters, there is no difference.

Otherwise:

char *s[];

s is an array of pointer to char. And

char **s;

s is a pointer to pointer to char.

You use the former if you need an array of pointer to char, and you use the latter if you need a pointer to a pointer to a char.

Upvotes: 7

Grigor
Grigor

Reputation: 4049

From my knowledge, **s is the address of the address of s, where *s[] is the address of array s, I think you would store single values in s, yet in s[] you would store array, and array itself is a pointer. Hope this helps!

Upvotes: 0

Related Questions