有一个问题要打印值的地址:
char word[] = "hi there"; //print address of string
int a = 1; // print address of 1
我知道如何打印变量的地址,我认为值在变量地址内?那么值的地址实际上是变量地址?
这是一个棘手的问题,我是对的吗?
提前致谢
答案 0 :(得分:9)
char word[]="hi there"; //print address of string
word
是名为char数组的对象的名称。它有一个地址和大小。
在这个地址上,有第一个元素,一个值为'h'
的char。以下字母跟随下一个地址,直到最后'e'
。接下来是一个0字节的字符串终结符。因此,给定的字符加上0字节,数组的总大小为9:8。
+--+--+--+--+--+--+--+--+--+
|h |i | |t |h |e |r |e |# | <-- # means NUL byte.
+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+
|68|69|20|74|68|65|72|65|00|
+--+--+--+--+--+--+--+--+--+
我们有一个专长:&word
和word
指向相同的地址,但它们代表的大小不同。 &word
指向整个数组,因此sizeof(*(&word))
为9,而word
指向第一个字符,因此sizeof(*word)
为1。
据说“word
衰变为指向第一个元素的指针。
正如评论中所述,请注意这与案例
略有不同char * wordptr = "hi there";
因为内存布局相同,但字符串位于只读内存中,而普通数据段包含指向该字符串的指针。因此&wordptr
,wordptr
和*wordptr
彼此完全不同:&wordptr
是指向数据记忆的char **
,wordptr
是{ {1}}指向RO内存(即,真实字符串 - 确切地说,指向字符串的第一个字符),而char *
只是开头的*wordptr
。
OTOH,
'h'
int a = 1; // print address of 1
是名为a
的对象的名称。它也有地址和大小。
它的大小依赖于实现,它的内存布局也是如此。让我们先拿一个最小字节的小端机器,假设每个int有4个字节:
int
您可以使用+--+--+--+--+
|01|00|00|00|
+--+--+--+--+
和&word
获取这两者的地址并将其打印出来:
&a
(printf("%p %p\n", &word, (void *)&a);
是必需的,因为在某些实现中,指针的大小可能会有所不同,所以为了安全起见,我们需要转换指针类型。)
“地址1”这个词没有意义;虽然使用(void *)
得到的地址的变量值为1,但这只是“巧合”:您可以设置&a
,并且地址保持不变,而存储在那里的值会发生变化。所以说“变量的地址正确地保持1”确实更好。
答案 1 :(得分:4)
如果您正在谈论在等号右侧打印值的地址,那么这是一个技巧问题。
等号右边的值是calld初始化器。
初始化者不需要(意味着由编译器决定是否有)地址,在您的情况下,即使他们有地址,您也无法访问它。
如果您正在谈论变量a
和word
的地址,那么这个问题很简单,因为如果您引用它们,它们将会有一个地址。
答案 2 :(得分:3)
图片可能有所帮助。我接受了你的声明
char word[] = "hi there";
int a = 1;
并将它们放在一个简单的程序中,然后使用我编写的一个小实用程序来显示内存中这些项的布局。我在我的系统上得到以下内存映射(SLES 10,gcc 4.1.2):
Item Address 00 01 02 03 ---- ------- -- -- -- -- "hi there" 0x400a32 'h' 'i' 20 't' 0x400a36 'h' 'e' 'r' 'e' 0x400a3a 00 '0' '1' 00 word 0x7fffb48d2ee0 'h' 'i' 20 't' 0x7fffb48d2ee4 'h' 'e' 'r' 'e' 0x7fffb48d2ee8 00 00 00 00 a 0x7fffb48d2edc 01 00 00 00
与数字文字不同,存储用于字符串文字。此存储在整个程序中可见,并在程序的生命周期内保持(它具有静态存储持续时间)。根据平台的不同,此存储可能是也可能不可写;最好假设它不是。您永远不应该尝试修改字符串文字的内容,并且尝试这样做会调用未定义的行为。
字符串文字"hi there"
有9个字节,从地址0x400a32
开始到地址0x400a3a
结束(0x400a3b
到0x400a3d
的字节不是字符串的一部分,包含一些随机值)。
字符数组word
也有9个字节,从地址0x7fffb48d2ee0
开始。已将字符串文字的内容复制到其中。
整数变量a
从地址0x7fffb48d2edc
开始为其设置了4个字节,它包含值1
(0x00000001
)。就像我之前说的那样,没有为1
这样的数字文字留出存储空间;编译器只需生成代码即可将值加载到a
中。
我正在处理的系统是 little-endian ,这意味着多字节值具有存储在低地址的最低有效字节(0x01
)(little-endian系统)读“从右到左”)。在 big-endian 系统上,最低有效字节将存储在高地址(big-endian系统读取“从左到右”)。同样,图片可能会有所帮助 - 如果我们存储二进制值0x12345678
,则各个字节将存储在地址A
中,如下所示:
Big endian: A+0 A+1 A+2 A+3 Value: 0x12 0x34 0x56 0x78 Little endian: A+3 A+2 A+1 A+0
请注意,在这种情况下,a
存储在低于word
的地址,即使它在源代码中的字后声明为。不要假设变量按照声明的顺序在内存中布局。
答案 3 :(得分:2)
您是否尝试过检查打印指针。我认为这可能会对你有所帮助。
地址使用%p 打印。来自规格: -
p 参数应该是指向void的指针。指针的值是 转换为一系列打印字符,在 实现定义的方式。
要在指针中打印地址,请使用如下: -
printf("%p",x)
在linux中,您可以使用plain gdb查看内存地址
答案 4 :(得分:2)
&
是“address-of”运算符,它生成一个指向其操作数的指针。
因此,&a
是一个有效的指针表达式,它保存变量a
的地址,因此该指针的值将使用以下语句打印。
printf("Address of a: %p",(void*)&a);
同样,如果你想要指向整个word[]
数组的指针,你可以通过以下方式打印:
printf("Pointer to Whole array: %p",(void*)&word);
如果您需要word[]
数组中第一个元素的地址,可以通过
printf("Address of first element in the word[]: %p",(void*)word);
您可以打印并看到上面两个printf()
语句为您提供相同的地址,但它们是不同的。阅读this
注意:强>
如果&
的操作数的类型为 type
,则结果为pointer to
type
。< / p>
&a
的结果为pointer to int
&word
的结果为pointer to array of 9 char
。由于size of (*(&word))
为9
对word
的引用包含pointer to char
类型。
答案 5 :(得分:0)
您可以使用&
运算符打印变量的地址:
int a = 1;
printf("Address of variable a is: %p",&a);