Difference between char *argv[] and char **argv for the second argument to main() [duplicate]
Asked Answered
R

4

30

CODE 1

#include<stdio.h>

int main(int argc, char *argv[])
{
int j;
printf("%d", argv[1][0]);
return 0;
}

CODE 2

#include<stdio.h>

int main(int argc, char **argv)
{
int j;
printf("%d", argv[1][0]);
return 0;
}

CODE 1 and CODE 2 both give same output. but argument 2 of main function in CODE 1 and CODE 2 are different. Array of pointers are created above data section at compile time. argv is array of pointers. Then we should declare argument in main function as pointer to pointer to character i.e., **argv. How it is correct to declare as in CODE 1?

Rodl answered 30/11, 2014 at 13:10 Comment(1)
Second parameter is not different in any way as far as compiler is concerned, that is char *argv[] is just equivalent to char **argv. That is more like matter of preferred coding style.Fennelflower
T
28

It is fundamental to c that char** x and char* x[] are two ways of expressing the same thing. Both declare that the parameter receives a pointer to an array of pointers. Recall that you can always write:

 char *parray[100];
 char **x;

 x = &parray[0];

and then use x identically.

Transitory answered 30/11, 2014 at 13:17 Comment(3)
Apart from the use of sizeofFielding
IMO, this answer would be significantly improved if you at least briefly noted that there are a few places in C (like the sizeof mentioned by Ed Heal) where arrays are not equivalent to pointers, and that the "array adjustment" in function parameter declarations (which the question asks about) is distinct from (though related to) the "array decay" in expressions. For references, you could cite e.g. What's a modern term for “array/pointer equivalence”? and Exception to array not decaying into a pointer?Cinque
@Ilmari-Karonen IMHO this answer is correct(however the example is wrong). Only because there are curly braces in a function signature it doesn't mean it will be an array variable! Truth is, C assumes it a normal pointer! That's even the only logical decision one could expect from C since if REALLY an array variable were assumed there nothing would be able to be assigned to it (array variable has no separate memory specific to itself as pointers do). So I believe that this is only a simplifying notation(chararr[]) provided by C which is exactly the same thing as the other notation(char*arr).Savage
T
14

Basically, char* argv[] means array of char pointers, whereas char** argv means pointer to a char pointer.

In any array, the name of the array is a pointer to first element of the array, that is, it contains the address of the first element.

So in the code given below, in char array x, x is a pointer to first element, '1', which is a character. So it's pointer to a character.

And in array arr, arr is pointer first element, x, which is itself a pointer to a character. So it a pointer to another pointer.

Hence, x is char*, and arr is char**.

While receiving something in a function, basic rule is that, you have to tell the type of the thing you are receiving. So either you simply say that you want to receive a char**, or you can also say char* arr[].

In first case, we don't need to think anything complex. We simply know, we are receiving an array of char*. Don't we know this? So, we receive it, and use it.

In second case, it is simple, as i have explained above that arr is a char**, you can put this as it's type and receive it safely. Now the system knows the type of the stuff we have received, we can access next elements by simply using array annotation. It's like, we have received the starting address of the array, we can surely go to the next elements, and as we know it's type, we know what it contains and how we can use that further. We know it contains pointer to char, so we can legally access them as well.

void func1(char* arr[])
{
    //function body
}
void func2(char** arr)
{
    //function body
}

int main()
{
    //x, y and z are pointer to char
    char x[3]={'1', '2', '3'};
    char y[3]={'4', '5', '6'};
    char z[3]={'7', '8', '9'};

    //arr is pointer to char pointer
    char* arr[3]={x, y, z};

    func1(arr);
    func2(arr);
}
Trainer answered 30/11, 2014 at 14:15 Comment(5)
There are a number of misconceptions in this answer, which have already confused at least one person. Firstly, char* argv[] and char** argv are absolutely equivalent, and do not mean different things at all. Secondly, arr is not a pointer. I didn't study the text close enough to identify other specific problems, but those are already serious to warrant a downvote and a sincere hope that you'll revisit this post before others get misled!Telegony
(absolutely equivalent in this context, at least)Telegony
@LightnessRacesinOrbit Re: Secondly, arr is not a pointer - perhaps comment what arr is and which arr - I see various uses in this answer.Pale
@chux: Good point. I was responding to the code comment and forgot to say so!Telegony
I agree that this answer is misleading! For one thing, array name is NOT a pointer! It is the "address" of the first element of the array, it does not CONTAIN it! As it has no separate location in memory! Please fix these mistakes or remove the answer.Savage
C
11

They're exactly the same. §5.1.2.2.2 of the C11 standard states:

The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

int main(void) { /* ... */ }

or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):

int main(int argc, char *argv[]) { /* ... */ }

or equivalent;10) or in some other implementation-defined manner.

10) Thus, int can be replaced by a typedef name defined as int, or the type of argv can be written as char ** argv, and so on.

Clearly the intent is for both declarations to be identical. On top of that, the rule is described in §6.7.6.3/7:

A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. ...

Consulate answered 30/11, 2014 at 15:12 Comment(0)
L
1

[EDIT] Using GCC at the time of the comment probably GCC 7.2

declaring an array like this

char array[]

makes it const which means that you CAN'T have the following code

char array[] = "hello";
array = "hey";

even though the second string is smaller and should fit you get this error

error: array type 'char [6]' is not assignable

if you have **argv you can write

main(int argc, char **argv)
{
    char **other_array;
    /*
     * do stuff with other_array
     */
    argv = other_array;
}

if you have *argv[] then

main(int argc, char *argv[])
{
    char **other_array;
    /*
     * do stuff with other_array
     */
    argv = other_array;
}

gives you this warning

warning: assigning to 'const char **' from 'char **' discards qualifiers in nested pointer types

so it is technically a small optimisation as if you had written const

Loot answered 13/2, 2017 at 13:37 Comment(2)
What?! certainly not, which compiler is this?Kentonkentucky
it was 3 1/2 years ago, I assume gcc 7, it certainly is not with gcc 10Loot

© 2022 - 2024 — McMap. All rights reserved.