what is this pointer to a character array supposed to represent [duplicate] - c

This question already has answers here:
What does int argc, char *argv[] mean?
(12 answers)
Closed 9 years ago.
i am really confused regarding this main function,
int main( int argc, char *argv[] ) {
/*statements*/
}
specifically the
char *argv[ ].
What does that represent exactly? i know that it is a pointer to an array of characters, but how is that array created and how does it work exactly? also is that char array the same as a string, since strings are an array or char?

It is a Command line argument.
You can just pass some values during execution of the program like below.
#include<stdio.h>
int main(int count,char *argv[]){
int i=0;
for(i=0;i<count;i++)
printf("\n%s",argv[i]);
return 0;
}
//save file as arg.c
In command line
C:\tc\bin>arg c JS
Output:
*c*
*JS*

It points to the parameters that are passed to your program when you launch it.
Ex:
./a.out toto tata
printf("argv[0]: %s, argv[1]: %s, argv[2]: %s, argv[3]: %s", argv[0], argv[1], argv[2], argv[3]);
Output:
argv[0]: ./a.out , argv[1]: toto, argv[2]: tata, argv[3]: (null)
argc is the number of arguments stored in argv.
You don't have to care about who created it, as it's part of the C standard. Search information about _start function if you really want to know.
argv is an array of string, and each individual string are each selfs arrays of char.
Some time you will see argv noted like this:**argv or argv[][].

char *argv[] is syntactic sugar for char **argv. argv is simply an array of pointers to null-terminated strings. The operating system creates the array for you before invoking your main() function.

int argc = Number of arguments/parameters when running the program (including program name)
char *argv[] = Arguments as an array of "strings" when running the program. This is how I think of it.
Example:
C:\> echo hello world
argc = 3
argv[0] = echo
argv[1] = hello
argv[2] = world

It points to the parameters passed by executing the java file. If you have a class called MyClass with a main method, by calling java myclass a b, you will have a and b in this array. Also in c or c++ calling myCommand a b...

The crucial facts is that it's an array of pointers to characters not a pointer to an array. So you have several pointers to characters, one per "word" in the program's argument list.

char *argv[] is the same as char **argv and argv[0] to argv[argvc-1] are pointers to C style strings(which are NULL terminated). The draft C99 standard actually provides a nice explanation for how it works and what the contents should be, from section 5.1.2.2.1 Program startup paragraph 2 says:
If they are declared, the parameters to the main function shall obey the following
constraints:
— The value of argc shall be nonnegative.
— argv[argc] shall be a null pointer.
— If the value of argc is greater than zero, the array members argv[0] through
argv[argc-1] inclusive shall contain pointers to strings, which are given
implementation-defined values by the host environment prior to program startup. The
intent is to supply to the program information determined prior to program startup
from elsewhere in the hosted environment. If the host environment is not capable of
supplying strings with letters in both uppercase and lowercase, the implementation
shall ensure that the strings are received in lowercase.
— If the value of argc is greater than zero, the string pointed to by argv[0]
represents the program name; argv[0][0] shall be the null character if the
program name is not available from the host environment. If the value of argc is
greater than one, the strings pointed to by argv[1] through argv[argc-1]
represent the program parameters.
— The parameters argc and argv and the strings pointed to by the argv array shall
be modifiable by the program, and retain their last-stored values between program
startup and program termination.

Related

If argc is 1, can I still use argv[1], argv[2],... character arrays?

If there is no argument passed from the command line ie. if argc is 1, can we still allocate memory for argv[1],argv[2],..... and use those buffers for further experiments.
If that is undefined behavior, can I still use it somehow?
No, the C standard does not specify that argv has any elements beyond argv[argc], so they may not exist in C’s object-memory model and the behavior of using them is not defined by the C standard.
C 2018 5.1.2.2.1 2 says:
…
argv[argc] shall be a null pointer.
If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup.
…
That is all there is that defines the extent of the argv array; nothing in the standard says there are more elements.
When argc is one, using argv[1] is defined but using argv[2] is not.
You can store new values to the defined elements because C 2018 5.1.2.2.1 2 also says:
The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.
can I access argv[] elements after argv[argc]?
You can ... but ONLY IN THIS CODE
#include <stdio.h>
int main(int argc, char **argv) {
if (argc == 1) {
char *foo[] = {"bar", "baz", "quux", NULL, "bingo"};
main(3, foo);
} else {
printf("argc is %d; argv[4] is \"%s\"\n", argc, argv[4]);
}
return 0;
}
See code running on ideone.
In all other codes, you cannot.
Always argv[argc] is equal to NULL. In the described case where argc is equal to 1 the array argv contains two pointers argv[0] and argv[1] where argv[1] is a null pointer.
You may reassign the pointers but this does not make a great sense because that will make your program unclear. Instead you could declare your own array if you need.

What does the "main()" that is put in the beginning of programs in C mean?

I just want to learn the basics thoroughly and what some simple codes refer to.
I was able to find a short description at
https://www.dummies.com/programming/c/looking-at-the-c-language/ but I dont think I fully understand it with the help of just that.
It's the starting point for your program. Per 5.1.2.2.1 Program startup of the C standard:
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; or in some other implementation-defined manner.
If they are declared, the parameters to the main function shall obey
the following constraints:
The value of argc shall be nonnegative.
argv[argc] shall be a null pointer.
If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to
strings, which are given implementation-defined values by the host
environment prior to program startup. The intent is to supply to the
program information determined prior to program startup from elsewhere
in the hosted environment. If the host environment is not capable of
supplying strings with letters in both uppercase and lowercase, the
implementation shall ensure that the strings are received in
lowercase.
If the value of argc is greater than zero, the string pointed to by argv[0] represents the program name; argv[0][0] shall be the
null character if the program name is not available from the host
environment. If the value of argc is greater than one, the strings
pointed to by argv[1] through argv[argc-1] represent the program
parameters.
The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their
last-stored values between program startup and program termination.

Passing Multiple Arguments to main()

For my class I need to create a function that takes in multiple parameters at runtime:
void main(int x, int y, int generation, char *layout[20])
However when the program runs with my input for these variables the information is not stored and in the debugging process
run 3 3 3 Test_Round
print x // returns 5
print y // returns -8779
How do I pass multiple arguments into the main function so main will recognize the parameters I give it?
Thanks everyone! I just used argv[1] and so on to get the proper data I need!
The standard is clear about how you need to declare your main function.
From the C99 Standard:
5.1.2.2.1 Program startup
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;9) or in some
other implementation-defined manner.
If they are declared, the
parameters to the main function shall obey the following constraints:
— The value of argc shall be nonnegative.
— argv[argc] shall be a null
pointer.
— If the value of argc is greater than zero, the array
members argv[0] through argv[argc-1] inclusive shall contain pointers
to strings, which are given implementation-defined values by the host
environment prior to program startup. The intent is to supply to the
program information determined prior to program startup from elsewhere
in the hosted environment. If the host environment is not capable of
supplying strings with letters in both uppercase and lowercase, the
implementation shall ensure that the strings are received in
lowercase.
— If the value of argc is greater than zero, the string
pointed to by argv[0] represents the program name; argv[0][0] shall be
the null character if the program name is not available from the host
environment. If the value of argc is greater than one, the strings
pointed to by argv[1] through argv[argc-1] represent the program
parameters.
— The parameters argc and argv and the strings pointed to
by the argv array shall be modifiable by the program, and retain their
last-stored values between program startup and program termination.
void main(int x, int y, int generation, char *layout[20])
is an invalid signature of main(). You need to use
int main(int argc, char *argv[])
where, argv[0] to argv[argc-1] will hold the parameters passed to main().
Quoting C11, chapter §5.1.2.2.2,
If the value of argc is greater than zero, the string pointed to by argv[0]
represents the program name; argv[0][0] shall be the null character if the
program name is not available from the host environment. If the value of argc is
greater than one, the strings pointed to by argv[1] through argv[argc-1]
represent the program parameters.
You can not pass more than two argument in main function. In main function, you can pass only two argument or Zero argument.
Using following parameters, you can pass the value command line.
int main(int argc, char *argv[])

true properties of argv command line argument container

I understand that command line arguments are pointed by the string pointers in the argv [] array. i.e. argv [0] contains a pointer to the name of the program and argv [1] a pointer to the very first command line argument.
But I noticed a very different application of argv on the internet and is written below. I have compiled it successfully and it print out the second arguments third character.
#include <stdio.h>
int main(int argc , char *argv []) {
printf("%c\n", argv [1][2]);
return 0; }
I have two question arising from this use.
What is the true dimension of argv? does it stop at two or is there more?
I have noticed it the code that the programer has used %c to access and print the pointed content. Now, we can always parse a pointer (a string pointer) to %s and expect it to print out the set of chars untill null terminator.
upto the best of my understanding %c can only be used if the array it self contains the character.
i.e.
char yadhavan [] = yadhavan is a boy;
printf ("%c", yadhavan [3]);
Could someone please explain how %c has been used with a pointer array?
A little more explanation is always more than welcome!
argv is of type char*[] and holds several strings(command line arguments).
argv[i] is of type char* and holds a string.
argv[i][j] is of type char and holds a character.
What is the true dimension of argv? Does it stop at two or is there more?
It depends on how many command line arguments there are.
Could someone please explain how %c has been used with a pointer array?
One can declare char pointers and make them point to strings or just use a char array and hold the string:
char* str="string";
Or
char str[]="string";
In both of these ways it is possible to refer a character using:
printf("%c",str[3]);
argv is actually an array of char*. So, it is possible to refer a single character from it.
What is the true dimension of argv? does it stop at two or is there more?
argc tells you the argument count (or the dimension of argv as you put it). In other words, the number of strings in argv is equal to argc. So, argv can contain more than two strings if multiple arguments are provided. For example, if I were to execute some command like
$ foo file1 file2 ...
argv would look like
argv[0] = "foo\0"
argv[1] = "file1\0"
argv[2] = "file2\0"
...
See this other answer for more details on argc vs argv.
Could someone please explain how %c has been used with a pointer array?
First, %s is used for printing strings. %c is used for printing a single character. Second, argv is an array of strings, and a string is simply an array of characters (char). So, argv is really an array of arrays of chars. So, when you see
printf("%c\n", argv[1][2]);
the code is printing out the third character of the second argument in argv. So, if I were to execute the command
$ foo bar
argc and argv would look like
argc = 2
argv[0] = "foo\0"
argv[1] = "bar\0"
argv[1][0] = 'b'
argv[1][1] = 'a'
argv[1][2] = 'r'
argv[1][3] = '\0' // null terminator
char *argv [] is array of pointers and this acts as a two dimention array, it can't contains more than 2D. So the data in 'argv' is very similar to 2D, but limitations are not specified. You can check in the below link:Limit on the number of arguments to main in C
#include <stdio.h>
int main(int argc , char *argv []) {
printf("%c\n", argv [1][2]);
return 0; }
Here char *argv [] is very similar to
Char argv[][] //with no argument limitation.

Is argv[n] writable?

C11 5.1.2.2.1/2 says:
The parameters argc and argv and the strings pointed to by the argv array shall
be modifiable by the program, and retain their last-stored values between program
startup and program termination.
My interpretation of this is that it specifies:
int main(int argc, char **argv)
{
if ( argv[0][0] )
argv[0][0] = 'x'; // OK
char *q;
argv = &q; // OK
}
however it does not say anything about:
int main(int argc, char **argv)
{
char buf[20];
argv[0] = buf;
}
Is argv[0] = buf; permitted?
I can see (at least) two possible arguments:
The above quote deliberately mentioned argv and argv[x][y] but not argv[x], so the intent was that it is not modifiable
argv is a pointer to non-const objects, so by in the absence of specific wording to the contrary, we should assume they are modifiable objects.
IMO, code like argv[1] = "123"; is UB (using the original argv).
"The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination." C11dr & C17dr1 §5.1.2.2.1 2
Recall that const came into C many years after C's creation.
Much like char *s = "abc"; is valid when it should be const char *s = "abc";. The need for const was not required else too much existing code would have be broken with the introduction of const.
Likewise, even if argv today should be considered char * const argv[] or some other signature with const, the lack of const in the char *argv[] does not completely specify the const-ness needs of the argv, argv[], or argv[][]. The const-ness needs would need to be driven by the spec.
From my reading, since the spec is silent on the issue, yet goes into depth about other assignments of main()'s argv = and argv[i][j] = , it is UB.
Undefined behavior is otherwise indicated in this International Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition of behavior" §4 2
[edit]:
main() is a very special function in C. What is allowable in other functions may or may not be allowed in main(). The C spec details attributes about its parameters that given the signature int argc, char *argv[] that shouldn't need. main(), unlike other functions in C, can have an alternate signature int main(void) and potentially others. main() is not reentrant. As the C spec goes out of its way to detail what can be modified: argc, argv, argv[][], it is reasonable to question if argv[] is modifiable due to its omission from the spec asserting that code can.
Given the specialty of main() and the omission of specifying that argv[] as modifiable, a conservative programmer would treat this greyness as UB, pending future C spec clarification.
If argv[i] is modifiable on a given platform, certainly the range of i should not exceed argc-1.
As "argv[argc] shall be a null pointer", assignining argv[argc] to something other than NULL appears to be a violation.
Although the strings are modifiable, code should not exceed the original string's length.
char *newstr = "abc";
if (strlen(newstr) <= strlen(argv[1]))
strcpy(argv[1], newstr);
1 No change with C17/18. Since that version was meant to clarify many things, it re-enforces this spec is adequate and not missing an "argv array elements shall be modifiable".
The argv array is not required to be modifiable (but may be in actual implementations). This is an intentional wording which was reaffirmed in the n849 meeting in 1998:
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n849.htm
PUBLIC REVIEW COMMENT #7
[...]
Comment 10.
Category: Request for information/clarification
Committee Draft subsection: 5.1.2.2.1
Title: argc/argv modifiability, part 2
Detailed description:
Is the array of pointers to char pointed to by argv modifiable?
Response Code: Q
This is currently implictly unspecified and the committee
has chosen to leave it that way.
In addition, two separate proposals were made to, respectively, change and augment the wording. Both were rejected. Interested readers can find them by searching for "argv".
argc is just an int and is modifiable without any restriction.
argv is a modifiable char **. It means that argv[i] = x is valid. But it does not say anything about argv[i] being itself modifiable. So argv[i][j] = c leads to undefined behaviour.
The getopt function of C standard library does modify argc and argv but never modifies the actual char arrays.
The answer is that argv is an array and yes, its contents are modifiable.
The key is earlier in the same section:
If the value of argc is greater than zero, the array members argv[0] through
argv[argc-1] inclusive shall contain pointers to strings, which are given
implementation-defined values by the host environment prior to program startup.
From this it is clear that argv is to be thought of as an array of a specific length (argc). Then *argv is a pointer to that array, having decayed to a pointer.
Read in this context, the statement to the effect that 'argv shall be modifiable...and retain its contents' clearly intends that the contents of that array be modifiable.
I concede that there remains some ambiguity in the wording, particularly as to what might happen if argc is modified.
Just to be clear, what I'm saying is that I read this language as meaning:
[the contents of the] argv [array] and the strings pointed to by the argv array shall be modifiable...
So both the pointers in the array and the strings they point to are in read-write memory, no harm is done by changing them, and both preserve their values for the life of the program. I would expect that this behaviour is to be found in all the major C/C++ runtime library implementations, without exception. This is not UB.
The ambiguity is the mention of argc. It is hard to imagine any purpose or any implementation in which the value of argc (which appears to be simply a local function parameter) could not be changed, so why mention it? The standard clearly states that a function can change the value of its parameters, so why treat argc specially in this respect? It is this unexpected mention of argc that has triggered this concern about argv, which would otherwise pass without remark. Delete argc from the sentence and the ambiguity disappears.
It is clearly mentioned that argv and argv[x][x] is modifiable. If argv is modifiable then it can point to another first element of an array of char and hence argv[x] can point to the first element of some another string. Ultimately argv[x] is modifiable too and that could be the reason that there is no need to mention it explicitly in standard.

Resources