简体   繁体   English

获取值而不取消引用C中的指针

[英]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). 我对C中的指针有点困惑。我的理解是,要从指针获取值,我们需要在前面添加星号(解除引用)。 So why is the below code where I define two pointers and then assign to them what argvs point to work just fine? 那么为什么下面的代码我定义了两个指针,然后分配给他们什么argvs指向工作就好了? However if I put asterisks in the printf it doesn't work? 但是,如果我在printf星号,它不起作用? Ie if my arguments are file_one and file_two the output will be file_one file_two 即如果我的参数是file_onefile_two则输出将是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** ). 'argument argv是一个指针指针( char**类型)。 The assignment in the code assigns argv[1] (which is of type char* ) to File_1 (which is also of type char* ). 代码中的赋值将argv[1] (其类型为char* )分配给File_1 (也是char*类型)。 In total, a char* is copied to another char* . 总的来说, char*被复制到另一个char* The pointers are not dereferenced any further as otherwise only one char would be copied, which is not desired. 指针不会被进一步解除引用,否则只会复制一个char ,这是不希望的。 In C, character strings are usually implemented as char* , and copying of only one char would contradict this semantic. 在C中,字符串通常实现为char* ,并且只复制一个char会与此语义相矛盾。

char *p = argv[1];

agrv is a double pointer so it can hold pointers argv[0] argv[1] and so on. agrv是一个双指针,所以它可以保存指针argv[0] argv[1] ,依此类推。

Now argv[1] is a pointer. 现在argv[1]是一个指针。 So the address of this pointer is being assigned to another pointer p of same type char 因此,该指针的地址被分配给相同类型char另一个指针p

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 在2D空间

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 正如在另一个答案中已经指出的那样, %s期望char *并且您只需传递char类型的指针并允许printf()执行解除引用的工作

PS : *p = p[0] PS :* p = p [0]

From printf(3) , here's the documentation for the s conversion specifier (ie %s ): printf(3) ,这里是s转换说明符的文档(即%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). 如果不存在l修饰符: const char *参数应该是指向字符类型数组(指向字符串的指针)的指针。 Characters from the array are written up to (but not including) a terminating null byte ('\\0'); 数组中的字符被写入(但不包括)终止空字节('\\ 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. 所以基本上printf本身就是取消引用它。 If you do a double indirection then it may lead to UB, because: 如果你做双重间接,那么它可能会导致UB,因为:

 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. 上面发送了File_1File_2指向的第一个字符,然后printf会尝试再次取消引用它,以为你在实际发送一个字符时发送了一个指向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. 尝试可视化内存中的内容: char** argv是指向指针的指针,两个指针恰好指向数组的开头。 The first array looks like [0][1] where each item is a pointer to a char * : 第一个数组看起来像[0][1] ,其中每个项目都是一个指向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. 其中["file_one"]实际上只是内存中指向'f'的指针,所以我们有'f', 'i', 'l', 'e', '_', 'o', 'n', 'e', '\\0'在内存中彼此相邻,空字节'\\0'告诉我们数组在哪里结束。

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 : 你的File_1现在包含一个指向第一个f的指针,当我们使用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. 它需要char * ,假设它是一个以空字符结尾的字符串,并在连续的内存位置取消引用指针,直到它到达空字节以便读入字符串的内容。

File_1 is a pointer to char variable. File_1char变量的指针。

while when you de-reference it using *File_1 , you refer to a char not a char * . 当你使用*File_1取消引用它时,你引用的是char而不是char *

Since printf uses %s for strings ie char * therefore, to print *File_1 you should use %c . 由于printf使用%s作为字符串,因此char *因此要打印*File_1您应该使用%c

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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