简体   繁体   中英

Get value without dereferencing the pointer in C

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM