I'm learning c programming, and I don't understand what is this asterisk for in the main method.
int main(int argc, char* argv[])
char* a; means that a is a pointer to variable of type char.
In your case argv is a pointer to a pointer (or even several of them - it is specified in argv in your case) to a variable(s) of type char. In other words, it's a pointer to an array (of length argv) of pointers to char variables.
You can even write your code this way: int main(int argc, char** argv) and nothing, actually, changes as soon as char* a is the same as char a[].
It means that argv is an array of character pointers.
The declaration char *argv[] declares argv as an array (of unknown size) of pointer to char.
For any type T, the declaration
T *p;
declares p as a pointer to T. Note that the * is bound to the identifier, not the type; in the declaration
T *a, b;
only a is declared as a pointer.
It signifies a pointer. char argv[] declares an array of characters. char* argv[] declares an array of character pointers, or pointers to strings.
Those are parameters passed from the command line to your program. This asterix is a pointer operator.
Basically char argv[] is an array of characters, char *argv[] is a pointer to an array of characters. So it is here to represent multiple strings to put it simply!
Note that: char *argv[] is equivalent to char * * argv, as char argv[] could be represented as char *argv.
Just to go further you would be amazed that those two expressions are equivalent:
int a[5];
int 5[a];
This is because an array of integers is a pointer to a set of integers in memory.
So a[1] can be represented as *(a + 1), a[2] as *(a + 2) etc. Which is equivalent to *(1 + a) or *(2 + a).
Anyway, pointers are like one of the most important and difficult notion to grasp when starting programming in C so I would suggest you taking a serious look at it on Google!
This " * " over here is, for sure to specify a pointer only, to place the argv[] //variable number of argument values// to a place it can fit.
Cause you don't know how many parameters will the user be passing as it is argc [argument count] and argv [argument value]. But we do want to allocate them a space where they can fit so we use a pointer with no defined specific SIZE, this pointer will automaticaly find and fit to appropriate memory location.
Hope this helped, if this didn't I'll be glad to help just let me know :)
Related
In command line arguments in C we can specify the arguments vector as char *argv[] or char **argv
i understand the first one which is an array of pointers to characters but what is the relationship between an array of pointers to characters and the second type which looks a pointer to pointer to character?
The difference between char *argv[] and char **argv is that:
char *argv[] is a array of char * pointers.
char **argv is a pointer to another pointer which points to a char.
char *argv[] can be visualized like this:
p1 -> "hello"
p2 -> "world"
p3 -> "!"
// p1, p2 and p3 are
// pointers to strings
// they have type char *
_________________
| p1| p2 | p3 |
—————————————————
// argv looks like this
// it is an array of all the pointers
when referencing the name of the array argv in an expression it will yield a pointer to the first element in the array.
The type of the array name argv when used in an expression is char **. This is because:
The array name argv decays to a pointer to the first element of the array.
The first element also happens to be a pointer, so argv is essentially a pointer to another pointer hence the type is char **
Function parameters that are arrays get implicitly adjusted by the compiler into a pointer to the first item of that array.
In case of the array char* argv[], it's an array of char* and a pointer to the first item is therefore a char**. Therefore it doesn't matter if you type char* argv[]or char**, they are equivalent in this specific case.
Also since the char* [] will get adjusted to char**, the size of the array doesn't matter. You could write char* argv [42] and that would be equivalent as well.
Subjectively, char* argv[] could be regarded as the most correct form, since it is 1) self-documenting - we are dealing with an array - and 2) the form used in the C standard 5.1.2.2.1 (hosted systems).
From my understanding so far,
char * argv[] = {"abc", "def"};
initialises an array of 2 char pointers. First one points to "abc", the second to "def". And the name argv is also a pointer that points to the first pointer in the array argv.
Why does some say argv is an array of char strings then? (like in the C Programming Language by K&R). Don't they mean an array of pointers to chars, which the book also explains.
If my hypothesis is correct, the %s in printf("%s", argv[1]) is not expecting a char string at all, rather, a pointer to the char string?
Thanks for your patience!
Stuff i've read:
Pointer to Pointer with argv
C: Accessing the second argv via a pointer
As used in the C standard, “A string is a contiguous sequence of characters terminated by and including the first null character” (C 2018 7.1.1 1). It is not a char *. A char * may point to the first character of a string and is sometimes referred to in the C standard as a pointer to a string, but this is sloppy terminology as a char * is necessarily a pointer to a character—there is no technical definition for what it means to point to a “sequence,” although we may take it to mean to point to the first element of a sequence.
From my understanding so far, char * argv[] = {"abc", "def"}; initialises an array of 2 char pointers.
That is correct.
And the name argv is also a pointer that points to the first pointer in the array argv.
That is not correct given the definition of argv in the question. The definition char * argv[] = {"abc", "def"}; defines argv to be an array of char *. It is not a pointer.
When an array is used as the operand of sizeof or unary &, it is operated on as an array. (Also, when an array is initialized with a string literal, the string literal is used as an array.) Other than these circumstances, when an array is used in an expression, it is converted to a pointer to its first element. This conversion is automatic and is so common that students may mistake the array, or the name of the array, for the pointer it is converted to. That is a mistake. The array is not a pointer.
Why does some say argv is an array of char strings then? (like in the C Programming Language by K&R).
Kernighan and Ritchie do not say this in either edition of The C Programming Language in any of the places listed for argv in the index. In the first edition, 1978, they say on page 110 “the second (argv) is a pointer to an array of character strings that contain the arguments, one per string.” In the second edition, 1988, they say on page 114 “the second (argv, for argument vector) is a pointer to an array of character strings that contain the arguments, one per string.” The index also lists page 163 for argv, but there is just an incidental mention there, referring to argv[0] for the program name.
Note that they refer to argv as a pointer rather than an array. This is because the argv parameter to main is a pointer. Although it may be declared with int main(int argc, char *argv[]), a parameter that is declared as an array is automatically adjusted to be a pointer. Thus char *argv[] in the declaration of main defines argv to be something different from the statement you showed, char * argv[] = {"abc", "def"};. In the parameter declaration, it is automatically adjusted to be a pointer. In the separate definition, it is an array.
Although Kernighan and Ritchie do refer to argv as a pointer, not an array as you wrote, they says it is a “pointer to an array.” This is also sloppy terminology. Its type is pointer-to-pointer-to-char, not pointer-to-array-of-char. It is a pointer to an array only in the sense that it is a pointer to the first element of an array of char.
If my hypothesis is correct, the %s in printf("%s", argv[1]) is not expecting a char string at all, rather, a pointer to the char string?
Per C 2018 7.21.6.1 8, for an s specifier to printf without a modifier or a precision, “the argument shall be a pointer to the initial element of an array of character type. Characters from the array are written up to (but not including) the terminating null character.” Thus, one should pass a char * (or a signed char * or unsigned char *) that points to the initial character of a string.
Char **argv points to an argument, and a character in that argument.
Example:
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* temp.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: albarret <marvin#42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2019/07/05 20:14:37 by albarret #+# #+# */
/* Updated: 2019/07/05 20:17:41 by albarret ### ########.fr */
/* */
/* ************************************************************************** */
#include <unistd.h>
void ft_putchar(char c)
{
write(1, &c, 1);
}
int main(int argc, char **argv)
{
int i;
i = 0;
if (argc < 2)
{
write(1, "\n", 1);
return (0);
}
while (argv[1][i])
{
ft_putchar(argv[1][i]);
i++;
}
write(1, "\n", 1);
return (0);
}
I create a clone of the echo command and that's more complicated than I was thinking.
Here my problem :
How works a char *argv[]? I know how works char myString[], but no that weird way to create strings :
It's a pointer on an array of chars, or an array of pointers on chars?
Why when I *argv[n], it shows me the n argument, not the n char... Chars can ve
char* argv[] behaves just like char** argv would behave. You could also use an char argv[][] the same way.
So basically, when you call *argv, you get argv[0] and *argv[n] gives you argv[0][n]
edit: to convert argv[x] into a std::string:
std::string s(argv[x]);
from that point on s is a standard string. But keep in mind that you must have zero terminated strings, this will not work for random binary data in a char**!
It's a pointer on an array of chars, or an array of pointers on chars?
In C, arrays are always passed as pointer to the first element. So, effectively you can treat it as char**, which is a pointer to pointer of char.
Why when I *argv[n], it shows me the n argument, not the n char... Chars can ve
You can split that expression according to the operator precedence:
char* p = argv[n];
char c = *p;
I am confused as to how the following passage matches up with the code that follows it:
Since argv is a pointer to an array of pointers, we can manipulate the
pointer rather than index the array. This next variant is based on
incrementing argv, which is a pointer to pointer to char, while argc
is counted down:
#include <stdio.h>
/* echo command-line arguments; 2nd version */
main(int argc, char *argv[])
{
while (--argc > 0)
printf("%s%s", *++argv, (argc > 1) ? " " : "");
printf("\n");
return 0;
}
Isn't char *argv[] just an array of pointers? Wouldn't a pointer to an array of pointers be written as char *(*argv[]) or something similar?
As a side note, is it normal that in general I find declarations that mix arrays and pointers rather confusing?
Such terms as "pointer to array" or "to point to an array" are often treated rather loosely in C terminology. They can mean at least two different things.
In the most strict and pedantic sense of the term, a "pointer to array" has to be declared with "pointer to array" type, as in
int a[10];
int (*p)[10] = &a;
In the above example p is declared as a pointer to array of 10 ints and it is actually initialized to point to such an array.
However, the term is also often used is its less formal meaning. In this example
int a[10];
int *p = &a;
p is declared as a mere pointer to int. It is initialized to point to the first element of array a. You can often hear and see people say that p in this case also "points to an array" of ints, even though this situation is semantically different from previous one. "Points to an array" in this case means "provides access to elements of an array through pointer arithmetic", as in p[5] or *(p + 3).
This is exactly what is meant by the phrase "...argv is a pointer to an array of pointers..." you quoted. argv's declaration in parameter list of main is equivalent to char **argv, meaning that argv is actually a pointer to a char * pointer. But since it physically points to the first element of some array of char * pointers (maintained by the calling code), it is correct to say semi-informally that argv points to an array of pointers.
That's exactly what is meant by the text you quoted.
Where C functions claim to accept arrays, strictly they accept pointers instead. The language does not distinguish between void fn(int *foo) {} and void fn(int foo[]). It doesn't even care if you have void fn(int foo[100]) and then pass that an array of int [10].
int main(int argc, char *argv[])
is the same as
int main(int argc, char **argv)
Consequently, argv points to the first element of an array of char pointers, but it is not itself an array type and it does not (formally) point to a whole array. But we know that array is there, and we can index into it to get the other elements.
In more complex cases, like accepting multi-dimensional arrays, it is only the first [] which drops back to a pointer (and which can be left unsized). The others remain as part of the type that is being pointed to, and they have an influence on pointer arithmetic.
The array-pointer equivalence thing only holds true only for function arguments, so while void fn(const char* argv[]) and void fn(const char** argv) are equivalent, it doesn't hold true when it comes to the variables you might want to pass TO the function.
Consider
void fn(const char** argv)
{
...
}
int main(int argc, const char* argv[])
{
fn(argv); // acceptable.
const char* meats[] = { "Chicken", "Cow", "Pizza" };
// "meats" is an array of const char* pointers, just like argv, so
fn(meats); // acceptable.
const char** meatPtr = meats;
fn(meatPtr); // because the previous call actually cast to this,.
// an array of character arrays.
const char vegetables[][10] = { "Avocado", "Pork", "Pepperoni" };
fn(vegetables); // does not compile.
return 0;
}
"vegetables" is not a pointer to a pointer, it points directly to the first character in a 3*10 contiguous character sequence. Replace fn(vegetables) in the above to get
int main(int argc, const char* argv[])
{
// an array of character arrays.
const char vegetables[][10] = { "Avocado", "Pork", "Pepperoni" };
printf("*vegetables = %c\n", *(const char*)vegetables);
return 0;
}
and the output is "A": vegetables itself is pointing directly - without indirection - to the characters, and not intermediate pointers.
The vegetables assignment is basically a shortcut for this:
const char* __vegetablesPtr = "Avocado\0\0\0Pork\0\0\0\0\0\0Pepperoni\0";
vegetables = __vegetablesPtr;
and
const char* roni = vegetables[2];
translates to
const char* roni = (&vegetables[0]) + (sizeof(*vegetables[0]) * /*dimension=*/10 * /*index=*/2);
Since argv is a pointer to an array of pointers.
This is wrong. argv is an array of pointers.
Since argv is a pointer to an array of pointers,
No, not even close.
Isn't char *argv[] just an array of pointers?
No, it's a pointer to pointers.
"Pointer to the first element of an array" is a common construct. Every string function uses it, including stdio functions that input and output strings. main uses it for argv.
"Pointer to an array" is a rare construct. I can't find any uses of it in the C standard library or POSIX. grepping all the headers I have installed locally (for '([^)]*\*[^)]) *\[') I find exactly 2 legitimate instances of pointer-to-array, one in libjpeg and one in gtk. (Both are struct members, not function parameters, but that's beside the point.)
So if we stick to official language, we have a rare thing with a short name and a similar but much more common thing with a long name. That's the opposite of the way human language naturally wants to work, so there's tension, which gets resolved in all but the most formal situations by using the short name "incorrectly".
The reason we don't just say "pointer to pointer" is that there's another common use of pointers as function parameters, in which the parameter points to a single object that's not a member of an array. For example, in
long strtol(const char *nptr, char **endptr, int base);
endptr is exactly the same type as argv is in main, both are pointer-to-pointer, but they're used in different ways. argv points to the first char * in an array of char *s; inside main you're expected to use it with indexes like argv[0], argv[optind], etc., or step through the array by incrementing it with ++argv.
endptr points to a single char *. Inside strtol, it is not useful to increment endptr or to refer to endptr[n] for any value of n other than zero.
That's semantic difference is expressed by the informal usage of "argv is a pointer to an array". The possible confusion with what "pointer to array" means in formal language is ignored, because the natural instinct to use concise language is stronger than the desire to adhere to a formal definition that tells you not to use the most obvious simple phrase because it's reserved for a situation that will almost never happen.
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".