C指针和物理地址

时间:2011-02-17 14:04:55

标签: c pointers

我刚刚开始C.我已阅读各种书籍/教程中的指针,并了解基础知识。但有一点我没有看到解释的是数字是多少。

例如:

int main(){
   int anumber = 10;
   int *apointer;

   apointer = &anumber;

   printf("%i", &apointer);
   }

可能会返回一个像4231168这样的数字。这个数字代表什么?它是RAM中的存储名称吗?

11 个答案:

答案 0 :(得分:9)

许多PC程序员一如既往地回复。以下是通用编程观点的回复。

在进行任何形式的硬件相关编程时,您会对地址的实际数值感兴趣。例如,您可以通过以下方式访问计算机中的硬件寄存器:

#define MY_REGISTER (*(volatile unsigned char*)0x1234)

此代码假设您知道位于地址0x1234的特定硬件寄存器。计算机中的所有地址都是按照传统/为方便起见以十六进制格式表示的。

在此示例中,地址长度为16位,这意味着所用计算机上的地址总线为16位宽。计算机中的每个存储单元都有一个地址。因此,在16位地址总线上,最多可以有2 ^ 16 = 65536个可寻址存储单元。 例如,在PC上,地址通常为32位长,为您提供429亿个可寻址存储单元,即4.29千兆字节。

详细解释该宏:

  • 0x1234是寄存器/存储单元的地址。
  • 我们需要通过指针访问此内存位置,因此我们将整数常量0x1234类型转换为unsigned char指针=指向字节的指针。
  • 这假设我们感兴趣的寄存器大1字节。如果它是两个字节大,我们可能会使用unsigned short。
  • 硬件寄存器可以随时更新(其内容为“易失性”),因此不允许程序对存储在其中的内容进行任何假设/优化。在代码中使用寄存器时,程序必须从寄存器中读取值。为了强制执行此行为,我们使用volatile关键字。
  • 最后,我们想要访问寄存器就像它是一个普通变量一样。因此添加*,以获取指针的内容。

现在程序可以访问特定的内存位置:

MY_REGISTER = 1;
unsigned char var = MY_REGISTER;

例如,像这样的代码在嵌入式应用程序中使用无处不在

(但正如在其他回复中已经提到的那样,你不能在现代PC中做这样的事情,因为他们正在使用一种叫做虚拟寻址的东西,如果你尝试的话就会给你一记耳光。)

答案 1 :(得分:7)

它是指针所指向的内存的地址或位置。但是,最好将此视为不透明的数量 - 您永远不会对指针的实际值感兴趣,只会对它所指的那个感兴趣。

地址与物理内存的关系如何是系统提供的服务,并且实际上在各个系统之间有所不同。

答案 2 :(得分:2)

这是anumber变量的虚拟地址。每个程序都有自己的内存空间,并且内存空间映射到物理内存。由处理器完成的映射id和用于该处理的服务数据由操作系统维护。所以你的程序永远不知道它在物理内存中的位置。

答案 3 :(得分:2)

它是存储变量的内存 1 位置的地址。您不应该关心确切的值,您应该知道不同的变量具有不同的地址,“连续的内存”(例如数组)具有连续的地址,...

顺便说一下,要打印存储在指针中的地址,您应该使用%p中的printf说明符。


  1. 请注意,我没有说“RAM”,因为在大多数现代操作系统中,您的进程看到的“内存”是虚拟内存,即操作系统管理的实际RAM的抽象。

答案 4 :(得分:1)

很多人告诉你,指针的数值会指定它的地址。这是一种方式实现如何实现它,但它非常重要,C标准对指针的说法是什么:

  • 当使用C编程语言操作时,nil指针始终为数值0。但是,包含指针的实际内存可以具有任何值,只要这个特殊的,依赖于体系结构的值始终处理为nil,并且实现注意该值被C源代码视为0。这一点很重要,因为在使用低级别内存调试器进行检查时,0指针在某些体系结构上可能会显示为不同的值。
  • 没有任何要求指针的值与实际地址有任何关系。它们也可以是抽象标识符,由LUT或类似的解析。
  • 如果指针指向数组,则指针算术的规则必须保持,即int array[128]; int a, b; a = (int)&array[120]; b = (int)&array[100]; a - b == 20 ; array + (a-b) == &array[20]; &array[120] == (int*)a
  • 指向不同对象的指针之间的指针算法未定义,导致未定义的行为。
  • 指向整数的映射指针必须是可逆的,即如果数字对应于有效指针,则转换为此指针必须有效。但是,对指向不同对象的指针的数字表示的(指针)算法是未定义的。

答案 5 :(得分:0)

是的,确切地说 - 它是内存中apointer数据的地址。诸如anumber和apointer之类的局部变量将在程序的堆栈中分配,因此它将引用堆栈中main()函数框架中的地址。

如果您使用malloc()分配了内存,那么它将引用程序堆空间中的位置。如果它是一个固定的字符串,它可能会引用程序数据或rodata(只读数据)段中的某个位置。

答案 6 :(得分:0)

在这种情况下,

& apointer表示指针变量apointer

的RAM存储器中的地址

答案 7 :(得分:0)

apointer是变量anumber的“地址”。从理论上讲,它可能是存储anumber值的RAM中的实际物理位置,但实际上(在大多数OS上),它可能是虚拟内存中的一个位置。结果是一样的。

答案 8 :(得分:0)

这是一个内存地址,最有可能是程序stack中的当前位置。与David的评论相反,有时您会计算指针偏移量,但这只是在您正在处理的某种数组时。

答案 9 :(得分:0)

这是指针的地址。

“anumber”在RAM中占用一些空间,此位置的数据包含数字10。

“apointer”也会在RAM中占用一些空间,此位置的数据包含RAM中“anumber”的位置。

所以,假设你有32个字节的ram,地址为0..31

例如位置16你有4个字节,“anumber”值10

例如位置20你有4个字节,“apointer”值16,“anumber”在RAM中的位置。

你打印的是20,apointer在RAM中的位置。

请注意,这不是直接在RAM中,而是在映射到RAM的虚拟地址空间中。为了理解指针,您可以完全忽略虚拟地址空间。

答案 10 :(得分:0)

它不是打印的变量数字的地址,而是打印的指针的地址。仔细查看。它只是“apointer”,然后我们就会看到数字变量的地址。