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".
Related
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
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;
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 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.
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 :)