简体   繁体   English

理解指针指针的概念

[英]Understanding pointer to pointer concept

I am a begineer in C and I am trying to understand pointer to pointer concept. 我是C的初学者,我试图理解指针指针的概念。 I have the following example 我有以下示例

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

Here my question why *(char *)names doesn't return me the 0x400658 ? 这里我的问题为什么*(char *)名称不会返回0x400658? From the above output i can see that value of (char *)names is 0x7fff167f7c00, now if i dereference this it should show me 0x400658 right ? 从上面的输出我可以看到(char *)名称的值是0x7fff167f7c00,现在,如果我取消引用它,它应该显示我0x400658对吗?

Could someone please explain me how this works ? 有人可以解释一下这是如何工作的吗?

EDITED after the initial question: 初步问题后编辑:

I did some further analysis and figured out some theory but still need help to understand. 我做了一些进一步的分析并找出了一些理论,但仍需要帮助才能理解。 When doing (char *)names, it thinks that it is pointer to char hence *(char *)names prints 1 byte of the address of 0x400658 ie 0x58. 在执行(char *)名称时,它认为它是指向char的指针因此*(char *)名称打印0x400658的地址的1字节,即0x58。 But in (char **)names case it thinks that as pointer to pointer and when dereferencing that it gives the whole address ie0x400658. 但在(char **)名称的情况下,它认为作为指针的指针,当解除引用时,它给出整个地址ie0x400658。 Below will help newbies like me to understand this more 下面将帮助像我这样的新手更多地了解这一点

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

Above was my theory but now lets say what i observed is correct but sometimes am getting below output 以上是我的理论,但现在让我说我观察到的是正确的,但有时我会低于输出

*(char **)notes =0x4007ec
*(char *)notes =0xffffffec 

here this should be 0xec considering my theory is correct ? 考虑到我的理论是正确的,这应该是0xec? why is it appended by ffff ? 为什么它附加了ffff? Am i missing something here ? 我错过了什么吗?

Here is how I read it: 以下是我的阅读方式:

// (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").

About 0xec . 关于0xec

This code: printf("*(char *)names = %p\\n", *(char *)names); 此代码: printf("*(char *)names = %p\\n", *(char *)names); prints a pointer (because of %p ) and the value given is a *(char *) ie a char . 打印指针(因为%p ),给定的值是*(char *)char

What happen is that the given char (1 byte) is converted to a pointer (8 bytes) before it is printed. 发生的事情是给定的char(1个字节)在打印之前被转换为指针(8个字节)。

This conversion is intended to fail. 此转换旨在失败。 You can not have a valid pointer from a single bit of data. 您不能拥有来自单个数据位的有效指针。

For 0x58 , as char is 88 and 88 as a 8 bytes integer is 0x00..0058 it is printed 0x58 . 对于0x58 ,因为char是88而88是8字节整数是0x00..0058它被打印为0x58

Char is a signed type. Char是签名类型。 0xec , as char is -20, and -20 as a 4 bytes signed integer is 0xffffffec , the sign byte fills all the new bits. 0xec ,因为char是-20,而作为4字节有符号整数的-20是0xffffffec ,符号字节填充所有新位。 That is called sign propagation . 这称为符号传播

So you can see that 0xec is converted to 0x00000000ffffffec . 所以你可以看到0xec被转换为0x00000000ffffffec Why the sign propagation only occurs on the first 4 bytes may have multiple explanations. 为什么符号传播仅发生在前4个字节上可能有多种解释。 The first I see is about performance. 我看到的第一个是性能。

Anyway, the char to pointer conversion will depend on the compiler, the target, etc... and because the result is intended to be unusable, it can be anything. 无论如何,char到指针的转换将取决于编译器,目标等......并且因为结果是无法使用的,所以它可以是任何东西。

Type of the names variable is a pointer to pointer to char. names变量的类型是指向char的指针。 By using expression *(char *)names you pretend that names is a pointer to char and dereference it, that is type of the *(char *)names expression is char. 通过使用表达式*(char *)名称,您假设名称是指向char的指针并取消引用它,即*(char *)名称表达式的类型为char。

You are bringing in errors by type casting a char** object to char* object . 您通过将char **对象类型转换为char *对象来引入错误。 Thus you cannot expect to get the same answer in both the cases. 因此,你不能指望在两种情况下得到相同的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM