理解指针指针的概念

时间:2015-03-21 06:49:51

标签: c pointers

我是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?我在这里错过了什么吗?

3 个答案:

答案 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 *对象来引入错误。因此,你不能指望在两种情况下得到相同的答案。