This question already has answers here:
What should main() return in C and C++?
(19 answers)
Closed 6 years ago.
I have the following function:
int func(int carg, const char **varg) {
//code ...
}
My understanding is the following:
varg is a pointer to a second pointer. This second pointer points to a char. This char is ...
either: a single char (1st case)
or: a char that constitutes the first char of a char array. (2nd case)
Is this understanding correct?
The thing I don't understand is why you would want to pass a pointer to a pointer as an argument.
If you wanted to pass (by reference) a single char to the function, you could simply write:
int func(int carg, const char *v) {
//code ...
}
In the 2nd case, where you want to pass (by reference) a char array to the function, one could use the same function (where this time, v points to the first element of the array passed to the function):
int func(int carg, const char *v) {
//code ...
}
In summary, I don't understand why you would want to use a pointer to a pointer as argument to a function.
The concrete case I have is the following declaration of a main function:
int main(int carg, const char **varg);
**varg handles the arguments on the command line.
One can access the command line arguments using varg[1], varg[2], etc.
So, obviously, what **varg does is simply to save the command line arguments in an array. But this could be achieved in a more simple way with the following code:
int main(int carg, const char *varg);
What am I missing?
To store a string you need an array of chars in memory. Pointer to any array in C is [type of array elements] * which is essentially pointer to first element in this array. In case of strings it is char *.
Arguments of command line is array of strings. That means, you have an array, where each element is cell in memory, containing pointer to another array - array of char. In this case type of elements in this array of pointers to array is char *, what give us proper type of pointer to this array (just substitute char * to formula above): char **.
Related
This question already has answers here:
C difference between *[] and **
(8 answers)
Closed 2 years ago.
CODE 1
#include<stdio.h>
int main(int argc, char *argv[])
{
int j;
printf("%d", argv[1][0]);
return 0;
}
CODE 2
#include<stdio.h>
int main(int argc, char **argv)
{
int j;
printf("%d", argv[1][0]);
return 0;
}
CODE 1 and CODE 2 both give same output. but argument 2 of main function in CODE 1 and CODE 2 are different. Array of pointers are created above data section at compile time. argv is array of pointers. Then we should declare argument in main function as pointer to pointer to character i.e., **argv. How it is correct to declare as in CODE 1?
It is fundamental to c that char** x and char* x[] are two ways of expressing the same thing. Both declare that the parameter receives a pointer to an array of pointers. Recall that you can always write:
char *parray[100];
char **x;
x = &parray[0];
and then use x identically.
Basically, char* argv[] means array of char pointers, whereas char** argv means pointer to a char pointer.
In any array, the name of the array is a pointer to first element of the array, that is, it contains the address of the first element.
So in the code given below, in char array x, x is a pointer to first element, '1', which is a character. So it's pointer to a character.
And in array arr, arr is pointer first element, x, which is itself a pointer to a character. So it a pointer to another pointer.
Hence, x is char*, and arr is char**.
While receiving something in a function, basic rule is that, you have to tell the type of the thing you are receiving. So either you simply say that you want to receive a char**, or you can also say char* arr[].
In first case, we don't need to think anything complex. We simply know, we are receiving an array of char*. Don't we know this? So, we receive it, and use it.
In second case, it is simple, as i have explained above that arr is a char**, you can put this as it's type and receive it safely. Now the system knows the type of the stuff we have received, we can access next elements by simply using array annotation. It's like, we have received the starting address of the array, we can surely go to the next elements, and as we know it's type, we know what it contains and how we can use that further. We know it contains pointer to char, so we can legally access them as well.
void func1(char* arr[])
{
//function body
}
void func2(char** arr)
{
//function body
}
int main()
{
//x, y and z are pointer to char
char x[3]={'1', '2', '3'};
char y[3]={'4', '5', '6'};
char z[3]={'7', '8', '9'};
//arr is pointer to char pointer
char* arr[3]={x, y, z};
func1(arr);
func2(arr);
}
They're exactly the same. §5.1.2.2.2 of the C11 standard states:
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;10) or in some other implementation-defined
manner.
10) Thus, int can be replaced by a typedef name defined as int, or
the type of argv can be written as char ** argv, and so on.
Clearly the intent is for both declarations to be identical. On top of that, the rule is described in §6.7.6.3/7:
A declaration of a parameter as ‘‘array of type’’ shall be adjusted
to ‘‘qualified pointer to
type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. ...
[EDIT] Using GCC at the time of the comment probably GCC 7.2
declaring an array like this
char array[]
makes it const which means that you CAN'T have the following code
char array[] = "hello";
array = "hey";
even though the second string is smaller and should fit you get this error
error: array type 'char [6]' is not assignable
if you have **argv you can write
main(int argc, char **argv)
{
char **other_array;
/*
* do stuff with other_array
*/
argv = other_array;
}
if you have *argv[] then
main(int argc, char *argv[])
{
char **other_array;
/*
* do stuff with other_array
*/
argv = other_array;
}
gives you this warning
warning: assigning to 'const char **' from 'char **' discards qualifiers in nested pointer types
so it is technically a small optimisation as if you had written const
Basically I have an array of words
void print(char *str) {
cout << str <<endl;
}
int main() {
int i =0;
char* name[] = {"Fred", "John", "Jimmy"};
print(*name[0]);
}
I would like to pass only first word to a function, but when I am doing in a way as I am doing right now it passes all the names.
You have an extra dereference there, the code should be like this:
print(name[0]);
Ideally, your print function should take const char*, because it does not modify the strings passed in.
char* name[] is an array of pointers to char, typically strings.
void print(char *str) requires a single pointer to a char as an argument.
By calling print(*name[0]), you are actually taking the first pointer from your name[] array, and dereferencing it to turn it into a single char. Since your function requires a pointer to char, you simply need to call it with print(name[0]) and you'll get the first item in your array.
Basically, I have an array of char* that I want to pass and modify in this function, so I pass in a pointer to an array of char*. That is, I want to pass a pointer to char* arr[]. What is the difference between the two?
As always, http://cdecl.org is your friend:
char * (*arr)[] - "declare arr as pointer to array of pointer to char"
char *** arr - "declare arr as pointer to pointer to pointer to char"
These are not the same. For a start, the first is an incomplete type (in order to use a pointer to an array, the compiler needs to know the array size).
Your aim isn't entirely clear. I'm guessing that really all you want to do is modify the underlying data in your array of char *. If so, then you can just pass a pointer to the first element:
void my_func(char **pointers) {
pointers[3] = NULL; // Modify an element in the array
}
char *array_of_pointers[10];
// The following two lines are equivalent
my_func(&array_of_pointers[0]);
my_func(array_of_pointers);
If you really want to pass a pointer to an array, then something like this would work:
void my_func(char *(*ptr)[10]) {
(*ptr)[3] = NULL; // Modify an element in the array
}
char *array_of_pointers[10];
// Note how this is different to either of the calls in the first example
my_func(&array_of_pointers);
For more info on the important difference between arrays and pointers, see the dedicated chapter of the C FAQ: http://c-faq.com/aryptr/index.html.
If you have a function that has char *(*arr)[] as a parameter, you will need to pass in an array with the address operator:
void afunc(char *(*arr)[]);
char *charptra, *charptrb, *charptrc;
char *arr[] = {charptra, charptrb, charptrc};
afunc(&arr);
On the other one, you have to pass a pointer that points to a pointer that points to a pointer:
void afunc(char ***);
char arr[] = "str";
char *arrptr = arr;
char **arrptrptr = &arrptr;
char ***arrptrptrptr = &arrptrptr;
afunc(arrptrptrptr);
I learning to use Pointers.
I have a few questions about an exercise code I wrote.
First, if I have the following function code:
//function prototype
void processCars(char *, char []);
int main(){
...
//actual callto the function
processCars(strModel[x], answer);
...
}
void processCars(char * string1, char string2[])
{
...
}
How would it be correct the define the arguments of this processCars function?
The first one - char * - is a pointer to char, which is the start location of the string (or better an array of chars) ?
The second is actually an array of chars directly.
Now, supposed I want to pass by reference a few array of strings and even array of structs. I managed to create the following code which works, but I still don't fully get what I'm doing.
typedef struct car {
char make[10];
char model[10];
int year;
int miles;
} aCar; // end type
// function prototype
void processCars( aCar * , char **, char **, int *, int *);
//aCar * - a pointer to struct of type car
//char **, char **
// int * - a pointer to integer
// Arrays passed as arguments are passed by reference.
// so this prototype works to
//void processCars( aCar * , char **, char **, int [], int []);
int main(){
aCar myCars[3]; // an array of 3 cars
char *strMakes[3]={"VW","Porsche","Audi"}; // array of 3 pointers?
char *strModel[3]={"Golf GTI","Carrera","TT"};
int intYears[3]={2009,2008,2010};
int intMilage[3]={8889,24367,5982};
// processCars(myCars, strMakes);
processCars(myCars, strMakes, strModel, intYears, intMilage);
return 0;
} // end main
// char ** strMakes is a pointer to array of pointers ?
void processCars( aCar * myCars, char ** strMakes, \
char ** strModel, int * intYears, \
int * intMilage ){
}
So, my qeustion is how to define this "char ** strMakes". What is it, why is it working for me?
I have also noticed, I can't change part of the string, because if I correct (or the references I read)
strings are read only. So, like in python, I can use array indices to access the letter V:
printf("\n%c",strMakes[0][0]);
But, unlike in python, I can't change it:
strMakes[0][0]="G" // will not work? or is there a way I could not think of?
So, thanks for reading through my long post and many question about pointers and c strings. Your answers are appreciated.
Within the function itself, both arguments will be pointers. The [] in the parameter list makes absolutely no difference, it's just syntactic sugar.
Although there is a distinct difference between an array and a pointer, a passed array to a function always decays to a pointer of the corresponding type. For example, an array of type char[3] would decay to char *, char *[3] would decay to char **.
char *strMakes[3] is an array of length 3 that holds pointers to strings stored somewhere else, probably in a read-only area of the process. An attempt to modify the strings themselves will result in undefined behaviour, most probably a protection fault.
If you want to be able to modify the strings, you could declare it as an array holding arrays, not pointers:
char strMakes[3][20] = {"VW", "Porsche", "Audi"};
This way the strings will be stored consecutively within the bounds of the outer array.
Another way is to still have an array of pointers, but the pointers should point to mutable memory:
/* these strings are mutable as long as you don't write past their end */
char str1[] = "VW";
char str2[] = "Porsche";
char str3[] = "Audi";
char *strMakes[3] = {str1, str2, str3};
Suppose I have an array of pointers to char in C:
char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };
And I wish to sort this array using qsort:
qsort(data, 5, sizeof(char *), compare_function);
I am unable to come up with the compare function. For some reason this doesn't work:
int compare_function(const void *name1, const void *name2)
{
const char *name1_ = (const char *)name1;
const char *name2_ = (const char *)name2;
return strcmp(name1_, name2_);
}
I did a lot of searching and found that I had to use ** inside of qsort:
int compare_function(const void *name1, const void *name2)
{
const char *name1_ = *(const char **)name1;
const char *name2_ = *(const char **)name2;
return strcmp(name1_, name2_);
}
And this works.
Can anyone explain the use of *(const char **)name1 in this function? I don't understand it at all. Why the double pointer? Why didn't my original function work?
Thanks, Boda Cydo.
If it helps keep things straight in your head, the type that you should cast the pointers to in your comparator is the same as the original type of the data pointer you pass into qsort (that the qsort docs call base). But for qsort to be generic, it just handles everything as void*, regardless of what it "really" is.
So, if you're sorting an array of ints, then you will pass in an int* (converted to void*). qsort will give you back two void* pointers to the comparator, which you convert to int*, and dereference to get the int values that you actually compare.
Now replace int with char*:
if you're sorting an array of char*, then you will pass in a char** (converted to void*). qsort will give you back two void* pointers to the comparator, which you convert to char**, and dereference to get the char* values you actually compare.
In your example, because you're using an array, the char** that you pass in is the result of the array of char* "decaying" to a pointer to its first element. Since the first element is a char*, a pointer to it is a char**.
Imagine your data was double data[5] .
Your compare method would receive pointers (double*, passed as void*) to the elements (double).
Now replace double with char* again.
qsort is general enough to sort arrays consisting of other things than pointers. That's why the size parameter is there. It cannot pass the array elements to the comparison function directly, as it does not know at compile time how large they are. Therefore it passes pointers. In your case you get pointers to char *, char **.
The comparison function takes pointers to the type of object that's in the array you want to sort. Since the array contains char *, your comparison function takes pointers to char *, aka char **.
Maybe it is easier to give you an code example from me. I am trying to sort an array of TreeNodes and the first few lines of my comparator looks like:
int compareTreeNode(const void* tt1, const void* tt2) {
const TreeNode *t1, *t2;
t1=*(const TreeNode**)tt1;
t2=*(const TreeNode**)tt2;
After that you do your comparison using t1 and t2.
from man qsort:
The contents of the array are sorted in ascending
order according to a comparison function pointed to by
compar, which is called with two arguments that **point**
to the objects being compared.
So it sounds like the comparison function gets pointers to the array elements. Now a pointer to a char * is a char **
(i.e. a pointer to a pointer to a character).
char *data[5] = { "boda", "cydo", "washington", "dc", "obama" };
is a statement asking the compiler for an array of size 5 of character pointers. You have initialized those pointers to string literals, but to the compiler, it's still an array of five pointers.
When you pass that array into qsort, the array of pointers decays into a pointer pointing to the first element, in accordance with C array parameter passing rules.
Therefore you must process one level of indirection before you can get to the actual character arrays containing the constants.
#bodacydo here is a program that may explain what other programmers are trying to convey but this would be in context of "integers"
#include <stdio.h>
int main()
{
int i , j;
int *x[2] = {&i, &j};
i = 10; j = 20;
printf("in main() address of i = %p, address of j = %p \r\n", &i, &j);
fun(x);
fun(x + 1);
return 0;
}
void fun(int **ptr)
{
printf("value(it would be an address) of decayed element received = %p, double dereferenced value is %d \r\n",*ptr, **ptr);
printf("the decayed value can also be printed as *(int **)ptr = %p \r\n", *(int **)ptr );
}
qsort() passes a pointer to the user-defined comparison function and as you have a char * (pointer to char array) hence your comparison function should dereference from pointer to pointer hence char **.