&是什么QUOT;非关联化"一个指针是什么意思? [英] What does "dereferencing" a pointer mean?

查看:314
本文介绍了&是什么QUOT;非关联化"一个指针是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请包括与解释的例子。

推荐答案

这是一般的足够好 - 除非你正在编写组件 - 设想一个 指针包含数字的内存地址,1指的是在这个过程中的存储器中的第二字节,2,第三,3第四等....

Reviewing the basic terminology

It's usually good enough - unless you're programming assembly - to envisage a pointer containing a numeric memory address, with 1 refering to the second byte in the process's memory, 2 the third, 3 the fourth and so on....


  • 发生了什么事0,第一个字节?好了,我们会得到以后 - 见的空指针的下面

  • 为了什么指针店更准确的定义,以及如何存储和地址联系,看的更多的内存地址,为什么你可能并不需要知道

  • What happened to 0 and the first byte? Well, we'll get to that later - see null pointers below.
  • For a more accurate definition of what pointers store, and how memory and addresses relate, see "More about memory addresses, and why you probably don't need to know".

当你想访问该指针指向内存中的数据/值 - 与数字索引地址的内容 - 那么你解引用指针

When you want to access the data/value in the memory that the pointer points to - the contents of the address with that numerical index - then you dereference the pointer.

不同的计算机语言有不同的符号来告诉你现在有兴趣指向的值,编译器或跨preTER - 下面我着重C和C ++

Different computer languages have different notations to tell the compiler or interpreter that you're now interested in the pointed-to value - I focus below on C and C++.

考虑用C下面给出...

Consider in C, given a pointer such as p below...

const char* p = "abc";

...四个字节与用于连接code中的字母'a','B','C',和一个0字节来表示文本数据的末尾的数值,被某处存储在内存和数据的数字地址存储在 p

例如,如果字符串正好是在地址为0x1000和 P 在一个的0x2000 32位指针,内存的内容将是:

For example, if the string literal happened to be at address 0x1000 and p a 32-bit pointer at 0x2000, the memory content would be:

Memory Address (hex)    Variable name    Contents
1000                                     'a' == 97 (ASCII)
1001                                     'b' == 98
1002                                     'c' == 99
1003                                     0
...
2000-2003               p                1000 hex

请注意,有对地址为0x1000没有变量名称/标识符,但我们可以间接参考字符串使用指针存储其地址: P

Note that there is no variable name/identifier for address 0x1000, but we can indirectly refer to the string literal using a pointer storing its address: p.

要参考字符 P 点,我们解引用 P 再次使用这些符号(中的一个, C):

To refer to the characters p points to, we dereference p using one of these notations (again, for C):

assert(*p == 'a');  // the first character at address p will be 'a'
assert(p[1] == 'b'); // p[1] actually dereferences a pointer created by adding
                     // p and 1 times the size of the things to which p points:
                     // in this case they're char which are 1 byte in C...
assert(*(p + 1) == 'b');  // another notation for p[1]

您也可以通过指向的数据移动指针,取消引用它们作为你去:

You can also move pointers through the pointed-to data, dereferencing them as you go:

++p;  // increment p so it's now 0x1001
assert(*p == 'b');  // p == 0x1001 which is where the 'b' is...

如果你有一些数据,可以写入,那么你可以做这样的事情:

If you have some data that can be written to, then you can do things like this:

int x = 2;
int* p_x = &x;  // put the address of the x variable into the pointer p_x
*p_x = 4;       // change the memory at the address in p_x to be 4
assert(x == 4); // check x is now 4

以上,则必须在编译时,你会需要一个叫做 X 变量已知的,code要求编译器安排,它应该被保存,确保该地址将可通过&放大器; X

Above, you must have known at compile time that you would need a variable called x, and the code asks the compiler to arrange where it should be stored, ensuring the address will be available via &x.

在C,如果你有一个变量是数据成员的结构,可以使用访问这些成员的 - > 提领运算符:

In C, if you have a variable that is a structure with data members, you can access those members using the -> dereferencing operator:

typedef struct X { int i_; double d_; } X;
X x;
X* p = &x;
p->d_ = 3.14159;  // dereference and access data member x.d_
(*p).d_ *= -1;    // another equivalent notation for accessing x.d_

多字节数据类型

要使用一个指针,计算机程序还需要一些洞察到正在指向的数据的类型 - 如果该数据类型需要多于一个字节重新present,则指针通常指向到最低-numbered字节的数据。

Multi-byte data types

To use a pointer, a computer program also needs some insight into the type of data that is being pointed at - if that data type needs more than one byte to represent, then the pointer normally points to the lowest-numbered byte in the data.

所以,看一个稍微复杂的例子:

So, looking at a slightly more complex example:

double sizes[] = { 10.3, 13.4, 11.2, 19.4 };
double* p = sizes;
assert(p[0] == 10.3);  // knows to look at all the bytes in the first double value
assert(p[1] == 13.4);  // actually looks at bytes from address p + 1 * sizeof(double)
                       // (sizeof(double) is almost always eight bytes)
assert(++p);           // advance p by sizeof(double)
assert(*p == 13.4);    // the double at memory beginning at address p has value 13.4
*(p + 2) = 29.8;       // change sizes[3] from 19.4 to 29.8
                       // note: earlier ++p and + 2 here => sizes[3]

指针动态分配的内存

有时候你不知道你会需要多少内存,直到你的程序正在运行,看到什么样的数据在它抛出......那么你可以使用动态分配内存的malloc 。通常的做法是,以该地址存储在指针...

Pointers to dynamically allocated memory

Sometimes you don't know how much memory you'll need until your program is running and sees what data is thrown at it... then you can dynamically allocate memory using malloc. It is common practice to store the address in a pointer...

int* p = malloc(sizeof(int));   // get some memory somewhere...
*p = 10;            // dereference the pointer to the memory, then write a value in
fn(*p);             // call a function, passing it the value at address p
(*p) += 3;          // change the value, adding 3 to it
free(p);            // release the memory back to the heap allocation library

在C ++中,内存分配通常与运营商完成,而用释放删除

In C++, memory allocation is normally done with the new operator, and deallocation with delete:

int* p = new int(10);   // memory for one int with initial value 10
delete p;

p = new int[10];      // memory for ten ints with unspecified initial value
delete[] p;

p = new int[10]();    // memory for ten ints that are value initialised (to 0)
delete[] p;

另请参阅 C ++智能指针的下面。

通常指针可能是在内存中存在的一些数据或缓冲液的唯一标志。如果需要持续的数据/缓冲的使用,而且能够根据需要调用免费()删除,以避免泄漏存储器,然后程序员必须对指针的一个拷贝操作...

Often a pointer may be the only indication of where some data or buffer exists in memory. If ongoing use of that data/buffer is needed, or the ability to call free() or delete to avoid leaking the memory, then the programmer must operate on a copy of the pointer...

const char* p = asprintf("name: %s", name);  // common but non-Standard printf-on-heap

// replace non-printable characters with underscores....
for (const char* q = p; *q; ++q)
    if (!isprint(*q))
        *q = '_';

printf("%s\n", p); // only q was modified
free(p);

...或者精心编排的任何更改逆转...

...or carefully orchestrate reversal of any changes...

const size_t n = ...;
p += n;
...
p -= n;  // restore earlier value...

C ++智能指针

在C ++中,它的使用智能指针对象来存储和管理指针的最佳实践,自动重新分配他们的时智能指针析构函数运行。由于C ++ 11标准库提供了两个, 的unique_ptr 了解时,有一个分配的对象单一所有者...

C++ smart pointers

In C++, it's best practice to use smart pointer objects to store and manage the pointers, automatically deallocating them when the smart pointers' destructors run. Since C++11 the Standard Library provides two, unique_ptr for when there's a single owner for an allocated object...

{
    std::unique_ptr<T> p{new T(42, "meaning")};
    call_a_function(p);
    // the function above might throw, so delete here is unreliable, but...
} // p's destructor's guaranteed to run "here", calling delete

...和 的shared_ptr 的股权(使用引用计数)...

{
    std::shared_ptr<T> p(new T(3.14, "pi"));
    number_storage.may_add(p); // might copy p into its container
} // p's destructor will only delete the T if number_storage didn't copy

空指针

在C, NULL 0 - 另外在C ++ nullptr - 可以被用来指示一个指针当前不持有一个变量的存储器地址,并且不应该被解除引用或指针运算中使用。例如:

null pointers

In C, NULL and 0 - and additionally in C++ nullptr - can be used to indicate that a pointer doesn't currently hold the memory address of a variable, and shouldn't be dereferenced or used in pointer arithmetic. For example:

const char* p_filename = NULL; // or "= 0", or "= nullptr" in C++
char c;
while ((c = getopt(argc, argv, "f:")) != EOF)
    switch (c) {
      case f: p_filename = optarg; break;
    }
if (p_filename)  // only NULL converts to false
    ...   // only get here if -f flag specified

在C和C ++,就像内置数字类型不一定默认为 0 ,也不的bool ,指针并不总是设置为 NULL 。所有这些都设置为当他们静态变量或(仅限于C ++)直接或间接的静态对象的成员变量或他们的基地,或进行零初始化0 /假/空(例如:新T(); 新T(X,Y,Z); 上执行零初始化T的成员包括指针,而新款T; 不)

In C and C++, just as inbuilt numeric types don't necessarily default to 0, nor bools to false, pointers are not always set to NULL. All these are set to 0/false/NULL when they're static variables or (C++ only) direct or indirect member variables of static objects or their bases, or undergo zero initialisation (e.g. new T(); and new T(x, y, z); perform zero-initialisation on T's members including pointers, whereas new T; does not).

此外,当您分配 0 NULL nullptr 来的指针中的指针中的位不一定都复位:指针可能不包含0,在硬件级,或在虚拟地址空间指到地址0。编译器允许存储别的东西存在,如果它的理由,但无论它 - 如果你来了,比较指针 0 NULL nullptr 或已分配的那些另一个指针,如预期的比较必须工作。因此,在下面的编译器级别的源$ C ​​$ C,空可能是有点神奇中的C和C ++语言....

Further, when you assign 0, NULL and nullptr to a pointer the bits in the pointer are not necessarily all reset: the pointer may not contain "0" at the hardware level, or refer to address 0 in your virtual address space. The compiler is allowed to store something else there if it has reason to, but whatever it does - if you come along and compare the pointer to 0, NULL, nullptr or another pointer that was assigned any of those, the comparison must work as expected. So, below the source code at the compiler level, "NULL" is potentially a bit "magical" in the C and C++ languages....

更严格,初始化指针存储一个比特模式,标识为 NULL 或一个(通常的虚拟)内存地址。

More strictly, initialised pointers store a bit-pattern identifying either NULL or a (often virtual) memory address.

的简单情况是,这是一个数字偏移到进程的整个虚拟地址空间;在更复杂的情况下,指针可相对于一些特定的存储区域,其中CPU可以基于CPU的段寄存器或连接在比特模式codeD段的id某种方式,和/或寻找在不同根据机器code指令使用地址的地方。

The simple case is where this is a numeric offset into the process's entire virtual address space; in more complex cases the pointer may be relative to some specific memory area, which the CPU may select based on CPU "segment" registers or some manner of segment id encoded in the bit-pattern, and/or looking in different places depending on the machine code instructions using the address.

例如,为int * 正确intialised指向一个 INT 变量可能 - 铸造到后浮法* - 在GPU内存从 INT 变量截然不同的访问值,那么一旦转换为一个函数指针可能是指不同的内存拿着机器操作codeS的功能。

For example, an int* properly intialised to point to a int variable might - after casting to a float* - access a value in "GPU" memory quite distinct from the int variable, then once cast to a function pointer might refer to distinct memory holding the machine opcodes for the function.

3GL编程语言往往隐藏这种复杂性,使得:

3GL programming languages like C and C++ tend to hide this complexity, such that:


  • 如果编译器给你一个指针变量或函数,可以取消对它的引用自由(只要变量的不破坏/释放的同时),它的编译器的问题,例如是否一个特定的CPU寄存器需要事先恢复,或使用一个独特的机code指令

  • if the compiler gives you a pointer to a variable or function, you can dereference it freely (as long as the variable's not destructed/deallocated meanwhile) and it's the compiler's problem whether e.g. a particular CPU register needs to be restored beforehand, or a distinct machine code instruction used

如果您在数组中获得一个指向一个元素,您可以使用指针运算到其他地方移动阵列中,甚至形成一个地址是合法的数组的一个过去的最末尾与其他指针数组中的元素(或者也同样被指针运算移动到相同的一个过去的非最终值)比较;又在C和C ++,它是由编译器,以确保本只是工程

if you get a pointer to an element in an array, you can use pointer arithmetic to move anywhere else in the array, or even to form an address one-past-the-end of the array that's legal to compare with other pointers to elements in the array (or that have similarly been moved by pointer arithmetic to the same one-past-the-end value); again in C and C++, it's up to the compiler to ensure this "just works"

操作系统特定的功能,例如共享内存映射可能会给你指点,他们会只是工作的地址是有道理的,他们的范围内

specific OS functions for e.g. shared memory mapping may give you pointers, and they'll "just work" within the range of addresses that makes sense for them

试图移动指针法律超越这些界限,或投任意数字的指针,或者转换为不相关类型使用指针,通常的 未定义行为,因此应避免在较高的水平库和应用程序,但code为操作系统,设备驱动程序等,可能需要依靠行为留下用C未定义或C ++,这是从来没有的非少为人其特定的硬件来定义。

attempts to move legal pointers beyond these boundaries, or to cast arbitrary numbers to pointers, or use pointers cast to unrelated types, typically have undefined behaviour, so should be avoided in higher level libraries and applications, but code for OSs, device drivers etc. may need to rely on behaviour left undefined by C or C++, that is never-the-less well defined by their specific hardware.

这篇关于&是什么QUOT;非关联化&QUOT;一个指针是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆