在C中打印指针

alc*_*ado 41 c pointers

我试图用指针理解一些东西,所以我写了这段代码:

#include <stdio.h>

int main(void)
{
    char s[] = "asd";
    char **p = &s;

    printf("The value of s is: %p\n", s);
    printf("The direction of s is: %p\n", &s);

    printf("The value of p is: %p\n", p);
    printf("The direction of p is: %p\n", &p);

    printf("The direction of s[0] is: %p\n", &s[0]);
    printf("The direction of s[1] is: %p\n", &s[1]);
    printf("The direction of s[2] is: %p\n", &s[2]);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

用gcc编译时我得到以下警告:

$ gcc main.c -o main-bin -ansi -pedantic -Wall -lm
main.c: In function ‘main’:
main.c:6: warning: initialization from incompatible pointer type
main.c:9: warning: format ‘%p’ expects type ‘void *’, but argument 2 has type ‘char (*)[4]’
main.c:11: warning: format ‘%p’ expects type ‘void *’, but argument 2 has type ‘char **’
main.c:12: warning: format ‘%p’ expects type ‘void *’, but argument 2 has type ‘char ***’
Run Code Online (Sandbox Code Playgroud)

(gcc的标志是因​​为我必须是C89)

为什么不兼容的指针类型?数组的名称不是指向它的第一个元素的指针吗?所以,如果s是指向'a'的指针,那么&s必须是a char **,不是吗?为什么我会收到其他警告?我是否必须使用(void *)转换指针才能打印它们?

跑步的时候我得到这样的东西:

$ ./main-bin
The value of s is: 0xbfb7c860
The direction of s is: 0xbfb7c860
The value of p is: 0xbfb7c860
The direction of p is: 0xbfb7c85c
The direction of s[0] is: 0xbfb7c860
The direction of s[1] is: 0xbfb7c861
The direction of s[2] is: 0xbfb7c862
Run Code Online (Sandbox Code Playgroud)

s的价值和它的方向(当然还有价值p)如何相同?

Jam*_*ran 27

"s"不是"char*",它是"char [4]".所以,"&s"不是"char**",而是"指向4个字符阵列的指针".您的编译器可能会将"&s"视为您编写了"&s [0]",这大致相同,但它是"char*".

当你写"char**p =&s;" 你试图说"我希望将p设置为当前指向"asd"的东西的地址.但是目前没有任何东西指向 "asd".只有一个数组保存 "asd";

char s[] = "asd";
char *p = &s[0];  // alternately you could use the shorthand char*p = s;
char **pp = &p;
Run Code Online (Sandbox Code Playgroud)


ind*_*div 16

是的,您的编译器期望void*.只是把它们变成无效*.

/* for instance... */
printf("The value of s is: %p\n", (void *) s);
printf("The direction of s is: %p\n", (void *) &s);
Run Code Online (Sandbox Code Playgroud)

  • 在变量函数中为`%p`格式的参数转换为`void*`实际上是语言标准的__required__. (9认同)
  • 这是真正需要使用 C 进行强制转换的极少数情况之一。 (2认同)

Air*_*Ltd 5

如果将数组的名称作为参数传递给函数,则会将其视为传递了数组的地址。所以 &s 和 s 是相同的参数。参见 K&R 5.3。&s[0] 与 &s 相同,因为它获取数组第一个元素的地址,这与获取数组本身的地址相同。

对于所有其他指针,尽管所有指针本质上都是内存位置,但它们仍然是类型化的,并且编译器会警告将一种类型的指针分配给另一种类型。

  • void* p;说p是内存地址,但我不知道内存里有什么
  • char* s;表示 s 是内存地址,第一个字节包含一个字符
  • char** ps;表示 ps 是一个内存地址,其中的四个字节(对于 32 位系统)包含一个 char* 类型的指针。

cf http://www.oberon2005.ru/paper/kr_c.pdf(K&R的电子书版本)