我在SO上遇到了这个问题:(棘手的指针问题):
AC程序员正在使用字节序为8位,字为4字节的低端机器。编译器支持不对齐访问,并使用1、2和4个字节分别存储char,short和int。程序员编写以下定义(右下方)以访问主存储器中的值(左下方):
Address | Byte offset
--------|-0--1--2--3----
0x04 | 10 00 00 00
0x08 | 61 72 62 33
0x0c | 33 00 00 00
0x10 | 78 0c 00 00
0x14 | 08 00 00 00
0x18 | 01 00 4c 03
0x1c | 18 00 00 00
int **i=(int **)0x04;
short **pps=(short **)0x1c;
struct i2c {
int i;
char *c;
}*p=(struct i2c*)0x10;
(a)写下以下C表达式的值:
**i
p->c[2]
&(*pps)[1]
++p->i
该问题仅回答了第三个子问题,但我想知道其余的子问题将如何解决。我是C语言的新手,并且试图提高我对指针的理解,这尤其令人困惑。谢谢你的帮助!
您可能需要参考以下内容:C和C ++中的运算符-运算符优先级
该问题未指定,但我们将假定指针为4个字节- sizeof(void*) == 4
。
int **i=(int **)0x04;
**i = ???
i
是指向的指针(指向int
)。当我们说时**i
,我们将两次取消对指针的引用-或读取指针指向的值。
首先要注意的是**i == *(*i)
。因此,我们首先从地址0x04的内存中读取了一个指针大小(4字节)的值。这是10 00 00 00
-解释为低端数字值,即0x10。所以现在我们离开了*((int*)0x10)
。这意味着我们int
从地址0x10的内存中读取了一个大小为4字节的值。78 0c 00 00
在little-endian中解释的值是0xC78。
struct i2c {
int i;
char *c;
} *p = (struct i2c*)0x10;
p->c[2] = ???
这有点棘手。我假定您了解结构只是变量的集合(不包括填充,此处不适用)在内存中一个接一个地布置。
我们的指针p
指向struct i2c
内存中0x10处的对象。这意味着在地址0x10是int
,名为p->i
。而紧随其后的是,在地址0x14的,就是char *
,命名p->c
。
该表达式的p->c[2]
意思是:“首先char *c
从p
指向的结构中获取the。然后char
从p->c
指向的数组中获取at索引2。”
所以首先,我们得到p->c
。我已经提到过这char*
是在地址0x14。在那里,我们找到了指针08 00 00 00
或0x8。
现在,我们有一个char *
指向地址0x8的,并且我们希望该char
数组中的索引为2。要获取数组元素的地址,我们使用以下公式:
&(x[y]) == (char*)x + (y * sizeof(x[0]))
换句话说,数组中第n
th个元素的偏移量(从数组的开始)是n
每个元素的大小的倍数。
由于char
s为1个字节,p->c[2]
因此位于0x8 + 2 = 0xA
。在那里我们找到了值0x62
,它是ASCII字符'b'
。
short **pps=(short **)0x1c;
&(*pps)[1] = ???
使用我们的知识运算符优先级,我们读&(*pps)[1]
为“ First dereference pps
,这是一个指向short的指针(或short的数组)。然后,我们想要元素的地址为索引1”。
在地址0x1C,我们有18 00 00 00
或0x18。因此,现在我们有了一个指向短裤数组的指针,该数组从地址0x18开始。使用上面的公式,知道short
s的大小为2个字节,我们将元素1计算为位于address 0x18 + (1 * 2) == 0x1A
。
地址0x1A是4c 03
或0x034C。但是,问题不是要我们提供元素1的值,而是要解决的(*pps)[1]
。相反,它要求该元素&(*pps)[1]
的地址。因此,我们只需回到上一段的末尾,即地址为0x1A。
++p->i = ??
对于这一点,您确实需要知道运算符的优先级。应该清楚的是,这可以用两种不同的方式解释:
p
1,然后取消引用p
以获取其成员i
p
以获取其成员i
,然后递增整数值从优先级图表中,我们看到->
优先级为2,而++
(前缀增量)的优先级较低,为3。这意味着我们需要先应用优先级->
,然后再应用增量。因此,选项b)是正确的。
因此,首先让我们开始吧p->i
。我们已经在第2部分中说过,既然p
指向地址0x10,并且i
是中的第一个成员struct i2c
,p->i
则它位于地址0x10。在那里,我们找到78 0c 00 00
或0xC78。
最后,我们需要应用++
运算符,并将该值递增到0xC79。
.....
1-指针算术意味着您将指针视为数组。因此,p + 3
这并不意味着“p
加3个字节”,而是“&p[3]
或p
(加上(3 * sizeof(* p))个字节)”。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句