I'm a little bit confused with the pointer in C. My understanding is that to get a value from a pointer we need to put asterisk in the front (dereferencing). So why is the below code where I define two pointers and then assign to them what argvs point to work just fine? However if I put asterisks in the printf
it doesn't work? Ie if my arguments are file_one
and file_two
the output will be file_one file_two
Thanks
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
char *File_1, *File_2;
File_1 = argv[1];
File_2 = argv[2];
printf("%s %s\n", File_1, File_2);
return EXIT_SUCCESS;
}
The 'argument vector' argv
is a pointer to a pointer (type char**
). The assignment in the code assigns argv[1]
(which is of type char*
) to File_1
(which is also of type char*
). In total, a char*
is copied to another char*
. The pointers are not dereferenced any further as otherwise only one char
would be copied, which is not desired. In C, character strings are usually implemented as char*
, and copying of only one char
would contradict this semantic.
char *p = argv[1];
agrv
is a double pointer so it can hold pointers argv[0]
argv[1]
and so on.
Now argv[1]
is a pointer. So the address of this pointer is being assigned to another pointer p
of same type char
Example:
char **p = malloc(sizeof(char*) * 2);/* double pointer */
p[0] = malloc(20); /* memory allocated to single pointer */
p[1] = malloc(20); /* memory allocated to single pointer */
strcpy(p[0],"string");
strcpy(p[1],"another");
printf("%s\n",p[0]);
printf("%s\n",p[1]);
In 2D space
int **p; /* Here p is double pointer */
*p is a single pointer.
As already pointed out in another answer %s
expects char *
and you just pass the pointer of type char and allow the printf()
to do job of dereferencing
PS : *p = p[0]
From printf(3)
, here's the documentation for the s
conversion specifier (ie %s
):
If no l modifier is present: The const char * argument is expected to be a pointer to an array of character type (pointer to a string). Characters from the array are written up to (but not including) a terminating null byte ('\\0'); if a precision is specified, no more than the number specified are written. If a precision is given, no null byte need be present; if the precision is not specified, or is greater than the size of the array, the array must contain a terminating null byte.
So basically printf
is dereferencing it inside itself. If you do a double indirection then it may lead to UB, because:
printf("%s %s\n", *File_1, *File_2);
The above sends 1st char pointed by File_1
and File_2
and then printf
would try to dereference it again inside thinking you sent a pointer to char when you actually sent a char.
Try to visualise what this looks like in memory: char** argv
is a pointer to a pointer, both pointers happen to point to the beginning of an array. The first array looks like [0][1]
where each item is a pointer to a char *
:
[0] -> ["file_one"]
[1] -> ["file_two"]
Where ["file_one"]
is actually just a pointer to 'f'
in memory, so we have 'f', 'i', 'l', 'e', '_', 'o', 'n', 'e', '\\0'
next to each other in memory and the null byte '\\0'
tells us where the array ends.
So when you assign:
char * File_1 = argv[1];
Your File_1
now contains a pointer to that first f
and when we use printf
:
printf("%s %s\n", File_1, File_2);
It takes that char *
, assumes it is a null terminated string, and dereferences the pointer at consecutive memory locations until it hits the null byte in order to read in the contents of the string.
File_1
is a pointer to char
variable.
while when you de-reference it using *File_1
, you refer to a char
not a char *
.
Since printf
uses %s
for strings ie char *
therefore, to print *File_1
you should use %c
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.