指针只是一个键值对吗?

时间:2014-03-21 17:47:08

标签: c++ pointers

指针只是一个键值对吗?例如:

int n = 3;
int *p = &n;
p; // <0x...>
&p; // 3

似乎与(在JavaScript中)类似:

var o = {}; // the memory on the computer
var p = '<0xfoo>'; // a key, an address, in the memory
var n = 3;
var o[p] = n; // create a key-value pair in memory
p; // '<0xfoo>';
o.p; // 3 <== dereference

这个比喻有用还是遗漏了什么?

5 个答案:

答案 0 :(得分:2)

我认为更好的类比是所有内存都是巨型数组,而指针是巨型数组的索引。巨型数组的每个元素都是1个字节(实际上是sizeof(char))。如果char *是您使用的唯一指针,那么这个比喻将近乎完美。

address {of &是巨型数组中元素的索引。

dereference *是某个索引处巨型数组中的一个元素。

复杂的是,不同的指针类型将连续的元素组合在一起。例如,int *大4字节,因此它希望在巨型数组中有4个连续的元素。

例如,如果int *intptr的索引为0x1000,那么它会假定它使用0x10000x10010x1002和{ {1}}保存int的值。

0x1003返回类型所需的元素数。例如,sizeof为1,sizeof(char)为4。

答案 1 :(得分:1)

我不认为这个比喻很有用。指针可以指向任何东西,包括它不能指向的内存区域,这会导致未定义的行为。考虑一下:

int *ptr = new int(123);
delete ptr;
// ptr no longer points to anything accessible,
// dereferencing it would yield undefined behaviour

或者这个:

int *f()
{
  int i = 123;
  return &i;
}

int *ptr = f();
// ptr no longer points to anything accessible,
// dereferencing it would yield undefined behaviour

或者这个:

struct S {};
S s;
int *ptr = reinterpret_cast<int*>(&s);
// bad cast, dereferencing ptr would yield undefined behaviour

所以,正如你所看到的,有一个&#34;键&#34; (指针)并不意味着有任何有效的&#34;值&#34; (指针)。

答案 2 :(得分:1)

你实际拥有的问题并不是正确的范式。我可以看到你正试图通过高级编程的经验闯入C编程语言的世界。第一个问题是为什么C?人们通常用C做什么?

为了更直接地回答您的问题,C是一种(唯一)语言,擅长直接操作内存和内存映射地址。在c中编程时,你需要对计算机体系结构有基本的了解(分配的东西,甚至分配意味着什么等等)。这里的指针基本上是一个字长值来保存一个地址,指针的类型给你一些线索,在那个地址中保存了什么。所以我建议不要将键值对与指针连接起来,这不是正确的“范式”。

历史上,人们使用C来做更多更高级别的事情,但是这些任务逐渐转移到具有更好表达能力的更高级语言,当然还有更差的性能。现在看看C意味着打入黑盒子并找出内部的内容,它不仅仅需要进行语言功能连接。要真正理解C,你需要准备一些计算机体系结构和周围o / s概念的知识,然后用那些“语言”而不是更高层次的概念来思考。

答案 3 :(得分:1)

以一种奇怪的方式,它是......但是你必须把它想象为在数组上操作而不是任何类型的稀疏容器,而这个数组是整个可寻址内存 in电脑。

然后,&#39;键&#39;是可用于查找字节的内存地址!它非常简单,但它给人们带来了困难,因为他们试图用抽象的术语来理解它。

内存是一个庞大的字节块,指针是其中一个字节的数字。

现在变得复杂的是当你将指针寻址的字节定义为字节以外的东西时。你可以说&#34;这个指针指向一个字符串,或一个结构&#39;然后你必须在心理上将指针所指的字节转换为其他字节。对于字符串,这很容易 - 指针所指的字节是字符串中的第一个字符,每个后续字节是下一个字符。指针仍然只处理第一个字符(即第一个字节),它取决于你(或你的编译器)处理剩下的字节作为一些更复杂的构造。

所以在C中,假设你有一个字符串,说&#34;你好&#34;,你有一个指向第一个字节的指针,你可以拿你的指针,给它加3并替换那个字节新地址&#39; Z&#39;然后你的字符串会读到&#39; HeZlo&#39;。您只需向指针添加3即可解决字符串中的第3个字节。但是 - 这里有一个让你绊倒的坑,如果你添加到你的指针,它现在指向3个字节的地址,而不是原始地址,所以你的字符串会读到&#39; Zlo&#39;因为你移动了#39;指针。由于这个原因,人们倾向于将指针视为一种更不透明的类型,因此它在概念上更容易不使用它们并导致像我刚才描述的问题。

随着时间的推移,语言编写者会进一步抽象它们,所以我们有智能指针和引用以及像javascript这样的花哨容器......但这些都是原始指针和内存的包装器。

聚苯乙烯。另一件需要理解的事情。你必须将指针数据存储在某处,它通常存储在程序数据中。所以指针是一个变量,因为变量只是内存中的字节,所以你可以有一个指向指针的指针,你可以修改指针 - 指针。

答案 4 :(得分:1)

我认为代码示例略有不同,但我可以看到分配给对象的变量几乎就像一个指针,因为它是一个“引用”类型而不是一个键值对。

例如在JavaScript中,

// Part 1:
var o = { foo: 'bar' };
var b = o;               // b acts like a pointer
b.foo = 'baz';
console.log(o.foo);      // will give you 'baz'

// Part 2:
// if you wanted you can reference another object with b now
b = {};
b.foo = 'bar';
console.log(o.foo);      // will still give you 'baz'

在C示例中,

int n = 3;
int m = 4;
int* p = &n;

printf('%d', *p);        // will give you 3 (the value of n)

// Part 1:
*p = 5;
printf('%d', n);         // will give you 5, because it acts like the b variable in the JavaScript example and "acts" on the memory address of n

// Part 2:
*p = &m;
*p = 10;
printf('%d', n);         // will still give you 5 because the reference of the pointer has changed like the second part of the JavaScript example