char x[16];
int y = 42 + 256;
char* p = &y;
int* q = p;
char** r = &p;
printf("%d %d %d\n", p, q, r);
为什么r的值总是小于p和q的12个单位?谢谢!
答案 0 :(得分:6)
您要打印的内容有三个内存地址。由于这些是在堆栈上分配的(假设它们不是全局的)我会期望类似:
2030 2026 2022
假设一个32位机器和4个字节指针。
double *
是指向指针的指针。如果使用正确的类型,它会变得更清晰。
char *str = "hello world";
在这种情况下, str
是指向以null结尾的字符序列的指针。
char **p = &str;
表示指向字符串的指针。
我说“正确的类型”,因为你有,例如:
int y = 42 + 256;
char* p = &y;
真的应该是:
int *p = &y;
在这个例子中使用char *
的通常原因是检查各个字节。
答案 1 :(得分:4)
让我们逐行分析您的代码:
char x[16];
x
是“char
”的数组[16],即它可以存储16个char
值。顺便说一下,您的代码中根本不使用x
。
int y = 42 + 256;
y
是int
,等于298。
char* p = &y;
p
是指向char
的指针,您正在尝试为其分配int
的地址。如果您需要指向int
的指针,则应将p
声明为int *p
,或者如果您需要通用指针,则应将其声明为void *p
。如果你真的想做你正在做的事情,你需要一个演员:char *p = (char *)&y;
。初始化p
的结果是p
指向y
的最低寻址字节。
int* q = p;
q
的类型为int *
,p
的类型为char *
。再次,你需要一个演员。假设演员,标准说明了你的最后两个陈述:
指向对象或不完整类型的指针可能会转换为指向不同对象或不完整类型的指针。如果生成的指针未针对指向类型正确对齐,则行为未定义。否则,当再次转换回来时, 结果应与原始指针进行比较。
所以,净效果就像你做的那样:int *q = &y;
。因此,q
包含y
的地址。
char **r = &p;
r
的类型为char **
。 &p
的类型为int **
。同样,您至少需要一个演员,但您无法将int **
移植到char **
。我不知道你为什么要使用char **
。如果您想在变量中使用p
的地址,则应使用void *
,或假设您确实需要char
,请使用char *
。
printf("%d %d %d\n", p, q, r);
您正在使用%d
格式说明符打印指针。 %d
需要int
,而不是指针。您应该使用%p
并将p
,q
和r
投射到void *
进行打印。
假设我明白你想做什么,我重写了你的程序:
#include <stdio.h>
int main(void)
{
int y = 42 + 256;
void *p = &y;
void *q = p;
void *r = &p;
printf("%p %p %p\n", p, q, r);
return 0;
}
在我的电脑上打印:
0x7fff5fbff7dc 0x7fff5fbff7dc 0x7fff5fbff7d0
p
和q
显然是平等的,r
是对象p
的地址。
如果我没有正确理解你的意图,你必须告诉我们你要做什么以及为什么。
答案 2 :(得分:3)
双指针是指向指针的指针。
为什么r的值总是12个单位 小于p和q?
如果您转移到另一个运行时或其他操作系统/编译器,那将不会停留。
答案 3 :(得分:0)
在您的代码中,与p或q相比,无法保证r的值。既然你说它更小,我猜它们是函数中的自动变量。您所看到的是这样一个事实:编译器(可能)为每个指针分配了4个字节,并且您已经分配了3个字节,这可以达到12个字节 - 这几乎是一个意外,但不是C的任何内容标准要求或类似的东西。例如,在64位系统上,您很可能会看到不同的数字。
char **是指向char的指针。典型的用途是创建一个动态的字符串数组。如果您开始使用以下内容可能会更容易理解:
typedef char *string;
string *string_array;
如果你将这些部分放在一起,它会说:char **string_array;