I recently learn the C language. I read that there is some ways to create an array of string. Is there any difference between char argv[][7]
and char *argv[]
? If there is not what do you prefer to use?

- 223,364
- 34
- 402
- 480

- 173
- 1
- 4
- 14
-
3have you tried compiling `char argv[][]`? – Cheers and hth. - Alf Apr 21 '14 at 12:53
-
1@close-voters: i rather doubt that this exact question has been asked before and has an answer... – Cheers and hth. - Alf Apr 21 '14 at 12:54
-
1@Jayesh: that is not the same question. – Cheers and hth. - Alf Apr 21 '14 at 12:59
-
@Cheersandhth.-Alf Actually I tried to compiling char argv[][7] and char *argv[]. – Bryan K. Apr 21 '14 at 13:00
-
`char argv[][]` vs. `char *argv[]` vs. `char **argv`... yep, different question. – crashmstr Apr 21 '14 at 13:00
-
1@BryanK. `char argv[][7]` is *not* what you have in your question! – crashmstr Apr 21 '14 at 13:01
-
@crashmstr Sorry, I just edited it. – Bryan K. Apr 21 '14 at 13:05
-
2@BryanK. Read [Difference between `char* str[]` and `char str[][]` and how both are stored in memory](http://stackoverflow.com/questions/17564608/what-does-the-array-name-mean-in-case-of-array-of-char-pointers/17661444#17661444) – Grijesh Chauhan Apr 21 '14 at 13:09
-
1@BryanK. specifically in the case of `argv` (assuming parameter of `main`), why would you want to *limit* anything about what is being passed? `argc` tells you how many strings you have and they are `null` terminated so you know how long they are. So what you are attempting makes no sense. – crashmstr Apr 21 '14 at 13:13
-
Since one has the number `7` in it there's obviously some difference :p – keyser Apr 21 '14 at 13:15
-
@crashmstr Actually I put specific name on my code, but I don't exactly know how to generalize it. I learned it today. Thank you – Bryan K. Apr 21 '14 at 13:17
4 Answers
Quoting from the C99 standard §6.2.5 ¶20 (Types)
An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. Array types are characterized by their element type and by the number of elements in the array.
The standard further says in §6.2.5 ¶22
An array type of unknown size is an incomplete type. It is completed, for an identifier of that type, by specifying the size in a later declaration (with internal or external linkage).
The array subscript operator []
has higher precedence than the *
operator. Therefore, the statement
char *argv[];
defines argv
to be an array of pointer to characters of unknown size since the array size is not specified. The array argv
is an incomplete type. This is assuming that the expression in the above statement does not appear as a function parameter. Since the array argv
is incomplete type, you must provide its size information before using it. This means you should make the above statement a declaration and provide its definition someplace else so that the linker will resolve it. Read this for the difference between declaration and definition -
What is the difference between a definition and a declaration?
// array declaration.
// this does not allocate space
// but only provides type information
// though of an incomplete type.
// argv must have internal or external linkage.
extern char *argv[];
// definition of the array.
// complete information and
// allocates memory for it.
// in the same translation unit or
// a different one.
char *argv[8];
You can also initialize the array with an array initializer list and the size of the array will be inferred from the list.
// size of the array argv is determined
// explicitly to be 2
char *argv[] = {"Hello", "World"};
// the above is equivalent to
char *argv[2];
argv[0] = "Hello";
argv[1] = "World";
Note: the above is just for demonstrating the array initialization without explicitly mentioning its size. String literal are read-only so the statement should better be written as
const char *argv[] = {"Hello", "World"};
If it appears as a function parameter however, then it's equivalent to char **argv
as in
int main(int argc; char *argv[]);
// equivalent to
int main(int argc, char **argv);
Same goes for the array in the below statement.
char argv[][7];
The above statement defines argv
to be an array of elements of type char[7]
, i.e., an array of 7
characters. The size of the array argv
is, again, not specified. Therefore, argv
is an incomplete type. Assuming it does not appear as a function parameter, the statement should be made into a declaration because it's an incomplete type and its definition should be provided elsewhere.
// array declaration.
// argv must have internal or external linkage
extern char argv[][7];
// definition.
// in the same translation unit
// or a different one
char argv[10][7];
The array can be initialized as in the previous case and the size will be determined implicitly from the initializer list.
// size of the array argv is inferred from
// the initializer list to be 3.
char argv[][7] = {{'a', 'b', 'c', 'd', 'e', 'f', 'g'},
{'a', 'b', 'c', 'd', 'e', 'f', 'g'},
{'a', 'b', 'c', 'd', 'e', 'f', 'g'}};
However, if the array expression appears as a function parameter, then it is equivalent to
char (*)[7]
, i.e., a pointer to an array of 7
characters.
void foo(char argv[][7]);
// equivalent to
void foo(char (*)[7])
This is because you cannot pass an array to a function. What actually gets passed is a pointer to the first element of array. Therefore, the array parameter in the function is implicitly converted to pointer to array element
type. Please read this for more detail -
Why do C and C++ compilers allow array lengths in function signatures when they're never enforced?
-
2You should add, that this syntax has meaning when initialized at time of declaration. – Grijesh Chauhan Apr 21 '14 at 13:20
-
1To clarify, `char argv[][7];` at file scope is a *tentative definition* and it has incomplete type. At block scope it is a constraint violation. – M.M Apr 21 '14 at 13:46
-
And the *declaration* `char *argv[];` (declarations are not statements in C, although they are in C++) is the same; it's invalid at block scope, and a tentative definition at file scope. – M.M Apr 21 '14 at 13:47
-
@MattMcNabb thanks. Updated my answer. Also, linked to your answer which is very much useful here. :) – ajay Apr 21 '14 at 13:56
-
2@MattMcNabb: the question is tagged both C and C++. tentative definitions are a C feature, not present in C++ (see C++11 appendix §C.1.2, first para). one could perhaps clearly diffentiate between the languages in each case, but as I see it the question is to blame... – Cheers and hth. - Alf Apr 21 '14 at 14:25
Try entering these at cdecl.org, and you will see
char argv[][7] : declare argv as array of array 7 of char
char *argv[] : declare argv as array of pointer to char
In other words, they are simply not the same thing. The first is an array of fixed-size character arrays (and other than you might expect, not necessarily nul-terminated!), whereas the other is an array to pointer-to-char, which also works as "C style string", that is a variable-length nul-terminated character sequence (the intent that is commonly behind argv
).

- 67,688
- 20
- 135
- 185
-
They are not the same, and only one of them is valid as a parameter in `main`. – juanchopanza Apr 21 '14 at 13:24
Firstly , it matters where this code appears. Actually these two declarators have different meanings in all 3 of the following scopes: function parameter list, block scope, and file scope.
In the function formal parameter list, char argv[][7]
means that argv
is a pointer to an array of 7 chars. char *argv[]
means that argv
is an array of pointers.
If we are taking about main()
, then char argv[][7]
is non-portable in that context and will probably cause a runtime error.
At block scope (i.e. inside a function), or file scope (global variables), we should not call things argv
as that name normally is used for the parameter of main()
, it is poor style to use it elsewhere with different semantics. We might have:
char foo[][7] = { "the", "quick", "brown" };
char *bar[] = { "the", "quick", "brown" };
Both of these are legal. In foo
, the chars all live inside the storage foo
, and are modifidiable. In bar
, the chars are not writable. bar
is an array of 3 pointers into the string table (in common implementations, anyway).
BTW you should write char const *
for type safety in the second one.
foo
wastes some memory because the strings are not always 7 chars long, but 7 chars are allocated for each array entry. bar
has an added level of indirection, but probably uses up less memory.
Finally, I'm not sure if you are also asking about the declarations:
char foo[][7];
char *bar[];
without initializers. If so, then these are illegal at block scope. In C++ they are illegal at file scope. In C, at file scope they are tentative definitions` which means that they declare an incomplete array type, and you should complete the type later in the file (probably by using one of the initialization examples we already discussed). This is a feature of C that is rarely useful.

- 138,810
- 21
- 208
- 365
If your doubt is the basic difference between these declarations, then,
char argv[][7];
is a 2-D array of characters with 7 columns. Defining the number of rows in not necessary.
char *argv[];
is an array of pointers to characters.
If you are confusing this with argument count and argument value,
int main(int argc, char *argv[])
Then please refer to

- 1
- 1

- 757
- 2
- 6
- 18