C++ 如何使用C语言中的内存地址?它们是六进制还是无符号整数?

C++ 如何使用C语言中的内存地址?它们是六进制还是无符号整数?,c++,c,pointers,memory,unsigned-integer,C++,C,Pointers,Memory,Unsigned Integer,我正在学习C语言,最近上了指针和内存地址的课。 老师告诉我们,内存位置基本上是无符号数字,因此我们可以使用以下代码显示它们: int a; printf("%u", &a); 或 的确,这是可行的,但我也在一些论坛上读到,应该使用%p或%x打印地址。所以,它们一定是十六进制数。。。我上面看到的整数实际上是十六进制数转换成十进制数吗?地址的基本形式是什么?十六进制、整数或简单的二进制数 请在这方面帮助我。基本形式的地址只是值。十六进制、二进制或八进制是数字的表示形式。例如,42,0x2a

我正在学习C语言,最近上了指针和内存地址的课。 老师告诉我们,内存位置基本上是无符号数字,因此我们可以使用以下代码显示它们:

int a;
printf("%u", &a);

的确,这是可行的,但我也在一些论坛上读到,应该使用%p或%x打印地址。所以,它们一定是十六进制数。。。我上面看到的整数实际上是十六进制数转换成十进制数吗?地址的基本形式是什么?十六进制、整数或简单的二进制数


请在这方面帮助我。

基本形式的地址只是值。十六进制、二进制或八进制是数字的表示形式。例如,
42
0x2a
2a16
052
528
1010102
1042
都是相同值的不同表示

就应该使用什么作为格式字符串而言,
%p
是正确的。无法保证无符号整数的位数与指针的位数相同,因此很可能会丢失信息

事实上,向
printf
提供与相应格式说明符不匹配的参数实际上是未定义的行为


使用
%u
%x
变体可以在大多数系统上很好地工作,其中指针和无符号整数大小兼容,但真正的可移植代码不依赖于此。例如,一个实现可以自由地使用一个16位无符号整数(以满足ISO C11附录E中的最小范围要求)和一个1024位指针类型(我必须找到其中一台计算机)。

在计算机中,如果仔细看,一切都是数字:)

指针实际上是一个数字。唯一的问题是,这个数字的大小取决于硬件架构和内存模型

例如,一些处理器使用64位地址,而微控制器可能只使用16位地址。
即使在64位处理器上,给定的进程也可能被限制为32位地址(通常是可以在64位处理器上运行的WIN32体系结构)

如果尝试使用%u打印指针,则不能保证整数的大小等于指针的大小。通常在WIN64体系结构上%u只显示指针的前32位


另一方面,%p格式考虑了实际指针大小,并保证正确显示其值。

打印对象地址的便携式方法是

int a, *p=&a;
printf("%p", (void *) p);
“%p”
说明符与
void*
匹配。C不为
int*
提供
printf()
说明符,但所有对象指针都可以转换为
void*

许多体系结构使用从0到某个大值的线性地址,该值可能超过
INT\u MAX
。然而C提供了许多地址方案。上述内容的输出可以是以下任何内容,不一定仅由数字字符组成:

123456789
0x0001C800
1000:0008
int:0000

以下是在C中执行此操作的标准方法:

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
  int x = 0;

  printf( "The value of &x is %" PRIxPTR " in hex and %" PRIuPTR
            " in decimal, and %%p displays %p.\n",
          (uintptr_t)&x,
          (uintptr_t)&x,
          (void*)&x);

  return EXIT_SUCCESS;
}
两者都是对的。 请尝试以下代码:

int a = 10;
printf("%p\n%u", &a, &a);
将以十六进制(%p)和uint(%u)打印指针地址。 如果将十六进制转换为uint,请在开发人员模式下使用windows计算, 您将具有相同的值

请阅读以下内容:


喝咖啡,继续编码!=)

学习C,每个人都必须克服的障碍之一就是与指针交朋友。在C语言中,和其他语言不同的是,您是在一个非常低级的机器上进行编码,而在C语言中所做的一切几乎都是一个内存操作。学习C的关键是知道“那个内存地址是什么?”,“我有多大的内存块?”以及“我如何正确使用它?”。不幸的是,很多时候,人们让这个过程变得比需要的困难得多

真正有帮助的一件事,也是理解大量低级编程的基础,就是所有变量都只是一个标签,或者更好的是,内存地址的别名

唯一区别普通变量和指针变量的是,它不是一个别名,其中一些直接立即值存储在内存中(如
5
21
),指针是指向存储其他内容的地址的内存位置的别名。简单地说,指针将内存地址存储为其值

以这种方式思考基本问题:

int x = 5;
什么是
x
?它是内存地址的标签。
x
标记了什么内存地址(别名)<代码>&x。那个地址存储了什么<代码>5。到目前为止还好吗

那么,什么是指针

int *y;         /* what's so special about the '*' in the declaration?
                   Nothing, just basic syntax for pointer declaration. */

y = &x;         /* which stores the address of x as the value of y.
                   And what is x? -- a label to a memory location */
什么是
y
?它是内存地址的标签。
y
标记了什么内存地址(别名)<代码>&y。那个地址存储了什么
&x
(x的地址)。还行吗

然后,让我们看一个简短的示例,希望有助于巩固基础知识,这样您就可以真正按照预期使用指针,访问和操作内存块,如数组、链表、堆栈等

#include <stdio.h>

void prn_values (int val, int *ptr);

int main (void) {

    int x = 5;          /* declare variable & pointer   */
    int *y = &x;        /* y now holds the address of x */
    prn_values (x, y);

    int z = 7;
    y = &z;             /* y now holds the address of z */
    prn_values (z, y);

    z = x;              /* y still holds the value of z,  */
    prn_values (z, y);  /* but the value of z has changed */

    *y = 9;             /* y still holds z, but we have changed z by     */
                        /* changing the value at the address stored in y */
    printf ("\n  z : %-14d (value)\n &z : %-14p (address)\n", z, &z);

    /* actually using a pointer to an array */
    char array[] = "pointer arithmetic.";
    char *p = array;    /* p points to the start address of array */

    printf ("\n array    : %p (address)\n array [0]: %p (address)\n\n",
            array, &array[0]);

    while (*p) {
        printf ("     %c    : %p\n", *p, p);
        p++;
    }

    return 0;
}

void prn_values (int val, int *ptr)
{
    printf ("\n  x : %-14d (value)\n &x : %-14p (address)\n", val, &val);

    printf ("  y : %-14p (value)\n &y : %-14p (address)\n *y : %-14d "
            "(dereference)\n", ptr, &ptr, *ptr);
}
输出

下面,整数指针
y
被分配
x
的值,然后
z
并输出指针地址处的值、地址和值注意指针的值是如何指向变量的地址的。当
y
指向
z
时,
z
的值会改变。由于
y
保存(指向)由
z
别名的内存地址,
*y
也反映了更改。然后注意改变是如何双向进行的。如果地址处的值由
y
i
int *y;         /* what's so special about the '*' in the declaration?
                   Nothing, just basic syntax for pointer declaration. */

y = &x;         /* which stores the address of x as the value of y.
                   And what is x? -- a label to a memory location */
#include <stdio.h>

void prn_values (int val, int *ptr);

int main (void) {

    int x = 5;          /* declare variable & pointer   */
    int *y = &x;        /* y now holds the address of x */
    prn_values (x, y);

    int z = 7;
    y = &z;             /* y now holds the address of z */
    prn_values (z, y);

    z = x;              /* y still holds the value of z,  */
    prn_values (z, y);  /* but the value of z has changed */

    *y = 9;             /* y still holds z, but we have changed z by     */
                        /* changing the value at the address stored in y */
    printf ("\n  z : %-14d (value)\n &z : %-14p (address)\n", z, &z);

    /* actually using a pointer to an array */
    char array[] = "pointer arithmetic.";
    char *p = array;    /* p points to the start address of array */

    printf ("\n array    : %p (address)\n array [0]: %p (address)\n\n",
            array, &array[0]);

    while (*p) {
        printf ("     %c    : %p\n", *p, p);
        p++;
    }

    return 0;
}

void prn_values (int val, int *ptr)
{
    printf ("\n  x : %-14d (value)\n &x : %-14p (address)\n", val, &val);

    printf ("  y : %-14p (value)\n &y : %-14p (address)\n *y : %-14d "
            "(dereference)\n", ptr, &ptr, *ptr);
}
gcc -Wall -Wextra -o pointers pointers.c
$ ./pointers

  x : 5              (value)
 &x : 0x7ffff2c72590 (address)
  y : 0x7ffff2c72590 (value)
 &y : 0x7ffff2c725b0 (address)
 *y : 5              (dereference)

  z : 7              (value)
 &z : 0x7ffff2c725a0 (address)
  y : 0x7ffff2c725a0 (value)
 &y : 0x7ffff2c725b0 (address)
 *y : 7              (dereference)

  z : 5              (value)
 &z : 0x7ffff2c725a0 (address)
  y : 0x7ffff2c725a0 (value)
 &y : 0x7ffff2c725b0 (address)
 *y : 5              (dereference)

  z : 9              (value)
  z : 0x7ffff2c725a0 (address)

 array    : 0x7ffff2c725c0 (address)
 array [0]: 0x7ffff2c725c0 (address)

     p    : 0x7ffff2c725c0
     o    : 0x7ffff2c725c1
     i    : 0x7ffff2c725c2
     n    : 0x7ffff2c725c3
     t    : 0x7ffff2c725c4
     e    : 0x7ffff2c725c5
     r    : 0x7ffff2c725c6
          : 0x7ffff2c725c7
     a    : 0x7ffff2c725c8
     r    : 0x7ffff2c725c9
     i    : 0x7ffff2c725ca
     t    : 0x7ffff2c725cb
     h    : 0x7ffff2c725cc
     m    : 0x7ffff2c725cd
     e    : 0x7ffff2c725ce
     t    : 0x7ffff2c725cf
     i    : 0x7ffff2c725d0
     c    : 0x7ffff2c725d1
     .    : 0x7ffff2c725d2