我是C的初学者,我正在尝试理解指向指针概念的指针。我有以下示例
int main() {
char *names[]={"Peter", "Dan"};
printf("names = %p\n", names);
printf("(char *)names = %p\n", (char *)names);
printf("(char **)names = %p\n", (char **)names);
printf("*(char *)names = %p\n", *(char *)names);
printf("*(char **)names = %p\n", *(char **)names);
return 0;
}
Output:
names = 0x7fff167f7c00
(char *)names = 0x7fff167f7c00
(char **)names = 0x7fff167f7c00
*(char *)names = 0x58
*(char **)names = 0x400658
这里我的问题为什么*(char *)名称不会返回0x400658?从上面的输出我可以看到(char *)名称的值是0x7fff167f7c00,现在,如果我取消引用它,它应该显示我0x400658对吗?
有人可以解释一下这是如何运作的吗?
在最初的问题之后编辑:
我做了一些进一步的分析并找出了一些理论,但仍然需要帮助才能理解。在执行(char *)名称时,它认为它是指向char的指针因此*(char *)名称打印0x400658的地址的1字节,即0x58。但是在(char **)名称的情况下,它认为作为指针的指针,当解除引用它给出整个地址,即.x400658。下面将帮助像我这样的新手更多地了解
printf("notes =%p\n", notes);
printf("(char *)notes+1 =%p\n", ((char *)notes+1));
printf("(char **)notes+1 =%p\n", ((char **)notes+1));
Output:
notes =0x7fff75e4c260
(char *)notes+1 =0x7fff75e4c261
(char **)notes+1 =0x7fff75e4c268
以上是我的理论,但现在可以说我观察到的是正确的,但有时候我会低于输出
*(char **)notes =0x4007ec
*(char *)notes =0xffffffec
考虑到我的理论是正确的,这里应该是0xec吗?为什么它附加了ffff?我在这里错过了什么吗?
答案 0 :(得分:3)
以下是我的阅读方式:
// (char*) is an address (of char): 8 bytes
(char *) names = 0x7fff167f7c00 // actual address of names
// (char**) is an address (of char*): 8 bytes
(char **) names = 0x7fff167f7c00 // actual address of names.
// *(char*) is a char: 1 byte.
*(char *) names = 0x58 // first byte of the first value of names (ie address of "Peter").
// *(char **) is an address (of char): 8 bytes
*(char **)names = 0x400658 // first value of names (ie address of "Peter").
关于0xec
。
此代码:printf("*(char *)names = %p\n", *(char *)names);
打印指针(由于%p
),给定的值为*(char *)
,即char
。
在给定的char(1字节)打印之前,它会被转换为指针(8个字节)。
此转换旨在失败。您不能拥有来自单个数据位的有效指针。
对于0x58
,由于char为88而88为8字节整数为0x00..0058
,因此打印0x58
。
Char是签名类型。 0xec
,因为char为-20,而-20为 4 字节有符号整数为0xffffffec
,符号字节将填充所有新位。这称为sign propagation。
因此,您可以看到0xec
已转换为0x00000000ffffffec
。为什么符号传播仅发生在前4个字节上可能有多种解释。我看到的第一个是性能。
无论如何,char到指针的转换将取决于编译器,目标等......并且因为结果是无法使用的,所以它可以是任何东西。
答案 1 :(得分:2)
names变量的类型是指向char的指针。 通过使用表达式*(char *)名称,您假设名称是指向char的指针并取消引用它,即*(char *)名称表达式的类型为char。
答案 2 :(得分:0)
您通过将char **对象类型转换为char *对象来引入错误。因此,你不能指望在两种情况下得到相同的答案。