As a C newbie, I have trouble to understand the following:
int main(int argc, char *argv[]) {
char **inputs = argv + 1;
char **inputs is a pointer to char *argv[] which is also a pointer, right? But why I have to add the "+1" at the end? Will this be an extra space for the '\0' character?
argv[0], or the first argument, is the string holding the name of your program.
argv[0] is the program you're currently running
argv[1+] are the arguments passed to the program
Perhaps not the best reference: https://www.gnu.org/software/gawk/manual/html_node/ARGC-and-ARGV.html
This is just to ignore the first entry which holds the path name that invoked the program. There is always at least one argument passed to main and this is it. Try passing some arguments yourself and print them..you'll get a better idea :)
To explain the "+1" in this context, we are doing pointer arithmetic. This is saying that you want the next memory address after whatever argv points to. Since argv points to the first address in an array of strings (char* in C), then the next memory address is guaranteed to be the second element in the sequence (arrays are laid out contiguously in memory). Thus, argv + 1 is equivalent to saying &argv[1].
As stated before, the first element in argv is just the program name. So you want everything after that for program inputs
Related
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.
K&R says the following about command line arguments:
The first [command line argument] conventionally called argc (for argument count) is the number of command-line arguments the program was invoked with; the second (argv, for argument vector) is a pointer to an array of character strings that contain the arguments, one per string.
As shown above, the second argument is described as a pointer to an array of strings. Just to clarify, is this saying that the second argument is a pointer to a single array that has multiple strings stored in it?
Wouldn't the syntax just be: main (int argc, char argv)
but the syntax is main (int argc, char *argv[])
The parameter syntax looks more like an array of pointers, where each element points to string constants or the first elements of strings in another array.
The loop construct to print what these pointers point at look more like what I just described:
for(i = 1; i < argc; i++)
printf("%s\n", argv[i])
Is the argument an array of pointers? If so, What do the elements actually point to? If it's not, what is the parameter?
In C, a "string" is actually char[].
Also, array (of any base type) in function signature is fully equivalent to pointer to the first element.
Each argument is a string, i.e. a char[], or char*.
An array of strings is char *[], or char**.
Therefore K&R are right, and the signature is what it should be.
BTW, argv[0] is typically the file name of the program and is not interesting unless you have multiple links to the same executable and are doing different things depending on the name by which your program was called. You can also use it for user feedback, such as usage instructions.
As far as I know, an array like
int example[10]
Is nothing else than a pointer to the first element in this array.
char* argv[]
Is an array of pointers; so that should be pointers which point to other pointers.
I have following problem now:
int main(int argc, char* argv[])
{
double ptrarg2=argv[2][1];
printf("beginletter=%c\nbeginpos=%d\n",&ptrarg2, ptrarg2);
return 0;
}
I am starting the program with ./program test and expecting the output to be:
beginletter=c
beginpos=123213123
While 123213123 should be the adress where the c is actually stored.
I am actually getting:
beginletter=
beginpos=0
what am I doing wrong? Thank you in advance!
It looks like argv[0] is going to be "./program", argv[1] is going to be "test", and argv[2] is going to be undefined or NULL because you don't have three arguments. The value of argc should tell you how many items there are in argv[]. My guess in this case is that the answer will be 2, and therefore only the first two (argv[0] and argv[1]) are valid.
There are several other strange things going on here. ptrarg2 is declared as a double, not as a char; the behavior here would be to convert the character to its floating point numeric equivalent and store that. Perhaps you meant ptrarg2 to be a char?
Next up, the printf() doesn't correspond very well to its additional arguments. &ptrarg2 is a double *, but you're assigning it to a %c (character) field, not a %p (pointer) field. ptrarg2 is a double, but you're assigning it to a %d (decimal number) field, not a %lf (long float, aka double) field. printf will happily try and print out values even when your types don't match, but they will be wrong, and crashing is quite possible.
&ptrarg2 is the address of the local variable, which is not the address that you are expecting. Just use argv[1][0] and argv[1]. argv[1][0] will give you the first character of the first argument, and argv[1] will give you the pointer to the first argument.
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("beginletter=%c\nbeginpos=%p\n",argv[1][0], argv[1]);
return 0;
}
I want to know how an array of strings is declared? What I do is I declare an array of pointers of pointers to strings. Eg.
char *array[]= {"string1","string2","string3"};
I was reading about modifying environment variables in Linux and stumbled upon the pointer char **environ ( http://www.cs.bham.ac.uk/resources/courses/2005/17423/doc/libc/Environment-Access.html#Environment-Access ).
char **environ is declared as an array of strings. I think it should be a pointer to a pointer. For eg.
char *array[]= {"string1","string2","string3"};
environ = array;
Am I doing something wrong?
I also read somewhere that char *argv[] = char **argv. How is it possible?
Edit: I also found this thread to be very helpful.
Should I use char** argv or char* argv[] in C?
you are mixing up two different things that are in fact difficult to know for someone who is learning C. Declaration of variables inside a function and as a function parameter are not the same thing. The equivalence
char*argv[] ~~~ char **argv
holds because this a parameter (of main). There the array is in fact the same thing as declaring a pointer.
Your assignment environ = array is not wrong, syntactically, the compiler will accept it. But it is wrong semantically for several reasons:
You don't know who and how is
allocated *environ.
You loose the reference to the
initial contents of *eviron.
You assign a local storage that will
be recycled once you leave the scope
of the function. So *environ will
be undefined, once you left the
function.
So environ is a particularly bad example to do such an assignment.
well the problem is this. In your program are several pointer. One you asign to a array of strings and one called environ that points to the environment variables. What you say to C with environ = array is give environ the same value as array.. but array has a pointer to a local array. So after that statement the environ pointer will just point to the array you made but has not made any changes to its previous content.
I think you need to strcpy all elements of array to environ. Or use a api call setenv (i think it is)
and to you'r second question. Yes the first pair of [] can always be rewritten to a pointer. so array[] = *array as is array[][5] = (*array)[5] and there for *array[] = **array
i hope to have helped you.
In C a string is basically just an array of chars. in addition an array name also represents its address.
this is the reason why argv[] is the address of the array of chars (which is a string) and *argv is also the address of the string (since it's the address of the first char).
Does ** have any special meaning in C?
Like this:
static intparse_one (int argc, char **argv)
{
cmd_line *slot;
int value;
Flag_name flag_name;
int i;
printf("argv %s\n",argv);
printf("argv[0] %c\n",**argv);
If so, does the line
**argv
make sense? A program I am trying to get to run is choking on it. If I try to print it I get a segmentation fault.
The first printf prints the string fine. The second printf fails.
Here is what I am getting for the output (The first line is correct):
argv -aps_instance1001-aps_ato0-aps_ipc_debug3
Segementation Fault (core dumped)
"Does ** have any special meaning in C?"
No, it is just two dereferences.
char **argv
means: argv dereferenced two times is a char. In other words argv is a pointer to a pointer to char.
The same for:
"If so, does the line: **argv make sense?"
The declaration says that **argv is a char. At runtime argv will be dereferenced two times; the value is the char that argv, the pointer to a pointer to char, is pointing to.
** is just two *.
As far as the segfault goes, look at your line printf("argv %s\n",argv);. The printf expects a char *, not char **, and so it's looking at an array of pointers rather than an array of characters. printf is trying to print everything at argv as a string of characters until it encounters a zero, and probably goes out of bounds before it finds one.
argv is a char **, which is a pointer to a pointer, or in this case an array of pointers. Don't print it directly, because it has no external meaning. (You can print the pointer value if you want to see it, of course.)
*argv or argv[0] is a char *, which is a pointer to char, which in this case is the first string in argv.
**argv is a char, which in this case is the first character of the first string in argv.
Yes.
char **argv
is the same thing as
char* argv[]
No.
Every * introduces a level of indirection. In this context, it means that argv is a pointer to a pointer. Which it is not, really, as technically you can see it a an array of pointers - it can be declared as char * argv[].
Obviously, by "no", I mean that ** is not special in itself. Or it is special, but neither more nor less than * or ***.
char **argv is same as char *argv[].
Here argv is the argument vector.
Isn't that a pointer to a pointer? I think the ** in front of the argv parameter has the same effect as ref in C#, in case you know C#.
While the string "**" does have a well defined meaning, I think the answer to the questions is "**" is not one operator, but two "*" in a row.
This is in contrast to Fortran where "**" is a single token and functions as the exponentiation operator.
So the meaning is well covered by Martin Beckett, but it really isn't "an operator".