C++ 如何使用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
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