在不取消引用 C 中的指针的情况下获取值

Get value without dereferencing the pointer in C

我对 C 中的指针有点困惑。我的理解是,要从指针中获取值,我们需要在前面加上星号(解引用)。那么,为什么在下面的代码中我定义了两个指针,然后将 argvs 指向的内容分配给它们就可以正常工作了? 但是,如果我在 printf 中加上星号,它不起作用吗? IE。如果我的参数是 file_onefile_two 输出将是 file_one file_two

谢谢

#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;
}

'argument vector' argv 是指向指针(类型char**)的指针。代码中的赋值是将argv[1](也是char*类型)赋值给File_1(也是char*类型)。总共,一个 char* 被复制到另一个 char*。指针不再被取消引用,否则只会复制一个 char,这是不希望的。在 C 中,字符串通常实现为 char*,仅复制一个 char 会与这种语义相矛盾。

File_1 是指向 char 变量的指针。

而当您使用 *File_1 取消引用时,您引用的是 char 而不是 char *

由于 printf 使用 %s 作为字符串,即 char * 因此,要打印 *File_1 你应该使用 %c.

char *p = argv[1];

agrv 是一个双指针,所以它可以容纳指针 argv[0] argv[1] 等等。

现在argv[1]是一个指针。所以这个指针的地址被分配给另一个相同类型char

的指针p

示例:

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]);

在二维中 space

int **p; /* Here p is double pointer */

*p is a single pointer.

正如另一个答案中已经指出的那样,%s 期望 char * 并且您只需传递 char 类型的指针并允许 printf() 完成取消引用的工作

PS: *p = p[0]

来自 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). Characters from the array are written up to (but not including) a terminating null byte ('[=18=]'); 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.

所以基本上 printf 是在其内部取消引用它。如果你做一个双重间接那么它可能会导致 UB,因为:

 printf("%s  %s\n", *File_1, *File_2);  

上面发送了由 File_1File_2 指向的第一个字符,然后 printf 会尝试在内部再次取消引用它,认为您实际上发送了一个 char 时发送了一个指向 char 的指针.

试着想象一下这在记忆中的样子: char** argv是一个指向指针的指针,两个指针恰好都指向一个数组的开头。第一个数组看起来像 [0][1],其中每个项目都是指向 char *:

的指针
[0] -> ["file_one"]
[1] -> ["file_two"]

其中 ["file_one"] 实际上只是内存中指向 'f' 的指针,因此我们在内存中彼此相邻的 'f', 'i', 'l', 'e', '_', 'o', 'n', 'e', '[=18=]' 空字节 '[=19=]' 告诉我们数组结束的地方。

所以当你赋值时:

char * File_1 = argv[1];

您的 File_1 现在包含指向第一个 f 的指针,当我们使用 printf 时:

printf("%s  %s\n", File_1, File_2);

它采用 char *,假定它是一个以空字符结尾的字符串,并取消引用连续内存位置的指针,直到它命中空字节,以便读入字符串的内容。