指针的值不是地址?

Pointer's value is not an address?

我有一个由 GET 方法调用的 CGI 脚本 (C 程序 test.elf)。这意味着数据附加到指向相同 CGI 脚本的 url 地址。例如:

http://.../cgi/c/test.elf?m=20&n=2000

这里我们发送数据集 m=20&n=2000,它与 url 的其余部分用问号 ? 分开。数据集中的单个变量也用 & 分隔。所以实际上我们发送的是 m=20n=2000

CGI 接口在调用时自动将发送的数据集 m=20&n=2000 存储在环境变量 QUERY_STRING 中,我希望我的 CGI 脚本首先打印它的 (a) 值和 (b)地址。

这是 CGI 脚本:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void){

    // getenv() returns a pointer to character (char*) and we need same type (char*) to store it.
    char* data;

    // We need an "array of characters" which is actualy the same as "string of characters".
    // Because strcpy() can only take pointer to the start of the array we also define another 
    // pointer and point it to array.
    char stored_enviromental_variable[1000];
    char* pointer;
    pointer = &stored_enviromental_variable[0];

    // ASCII HTML header
    printf("content-type:text/html; charset=utf-8\n\n");

    printf("<h1>Multiplication result</h1>");

    // Pointer now points to enviromental variable.
    data = getenv("QUERY_STRING");

    // We store the value of pointer
    strcpy(pointer, data);

    // We print some information.
    printf("%s: %s<br>", "Value of the \"QUERY_STRING\"", stored_enviromental_variable);
    printf("%s: %x<br>", "Address of the \"QUERY_STRING\"", data);

}

编译时出现警告:

[ziga@localhost ~]$ gcc -Wpedantic -std=c18 -Wall -o test.elf test.c 
test.c: In function ‘main’:
test.c:42:15: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 3 has type ‘char *’ [-Wformat=]
  printf("%s: %x<br>", "Address of the \"QUERY_STRING\"", data);
              ~^                                          ~~~~
              %s

看来是这个源代码导致了问题:

printf("%s: %x<br>", "Address of the \"QUERY_STRING\"", data);

这对我来说很奇怪,因为我认为 "pointer always stores location"。那么,为什么 data 存储一个字符呢?我怎样才能删除警告?


如果我在我得到这个的浏览器中调用 CGI 脚本:

如错误消息所述,printf%x 格式说明符需要一个 unsigned int 参数,但您传入的 data 类型为 char *.

要打印指针值,您应该使用 %p 格式说明符。此外,参数必须转换为 void *:

printf("%s: %p<br>", "Address of the \"QUERY_STRING\"", (void *)data);