c指针和内存表示

用户名

我在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


1。

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。


2。

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 *cp指向的结构中获取the。然后charp->c指向的数组中获取at索引2。

所以首先,我们得到p->c我已经提到过这char*是在地址0x14。在那里,我们找到了指针08 00 00 00或0x8。

现在,我们有一个char *指向地址0x8的,并且我们希望该char数组中的索引为2。要获取数组元素的地址,我们使用以下公式:

&(x[y])  ==  (char*)x + (y * sizeof(x[0]))

换句话说,数组中第nth个元素的偏移量(从数组的开始)n每个元素的大小的倍数。

由于chars为1个字节,p->c[2]因此位于0x8 + 2 = 0xA在那里我们找到了值0x62,它是ASCII字符'b'


3。

short **pps=(short **)0x1c;

&(*pps)[1] = ???

使用我们的知识运算符优先级,我们读&(*pps)[1]为“ First dereference pps,这是一个指向short的指针(或short的数组)。然后,我们想要元素地址为索引1”。

在地址0x1C,我们有18 00 00 00或0x18。因此,现在我们有了一个指向短裤数组的指针,该数组从地址0x18开始。使用上面的公式,知道shorts的大小为2个字节,我们将元素1计算为位于address 0x18 + (1 * 2) == 0x1A

地址0x1A是4c 03或0x034C。但是,问题不是要我们提供元素1的值,而是要解决的(*pps)[1]相反,它要求该元素&(*pps)[1]地址因此,我们只需回到上一段的末尾,即地址为0x1A。


4。

++p->i = ??

对于这一点,您确实需要知道运算符的优先级。应该清楚的是,这可以用两种不同的方式解释:

  • a)递增指针p 1,然后取消引用p以获取其成员i
  • b)解除引用p以获取其成员i,然后递增整数值

优先级图表中,我们看到->优先级为2,而++前缀增量)的优先级较低,为3。这意味着我们需要先应用优先级->,然后再应用增量。因此,选项b)是正确的。

因此,首先让我们开始吧p->i我们已经在第2部分中说过,既然p指向地址0x10,并且i是中的第一个成员struct i2cp->i则它位于地址0x10。在那里,我们找到78 0c 00 00或0xC78。

最后,我们需要应用++运算符,并将该值递增到0xC79。

.....

1-指针算术意味着您将指针视为数组。因此,p + 3这并不意味着“p加3个字节”,而是“&p[3]p(加上(3 * sizeof(* p))个字节)”。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

C指针和内存泄漏

来自分类Dev

C ++指针和内存泄漏

来自分类Dev

C ++中的constexpr指针和内存管理

来自分类Dev

C ++中的constexpr指针和内存管理

来自分类Dev

内存管理 C 和指针的 free()

来自分类Dev

c++ 指针和内存泄漏 - 答案

来自分类Dev

理解c中的内存分配和指针

来自分类Dev

就内存分配而言,C ++指针和指针身份

来自分类Dev

C和C ++中的指针和动态内存

来自分类Dev

内存寻址和指针

来自分类Dev

内存泄漏C ++指针

来自分类Dev

C语言中指向结构和内存分配的指针

来自分类Dev

为结构C ++中的指针分配和删除内存

来自分类Dev

C ++读取内存地址/指针和偏移量

来自分类Dev

为什么C ++无法同时释放内存和指针

来自分类Dev

C中的函数指针和内存地址

来自分类Dev

C ++控制内存访问和指针解引用

来自分类Dev

为结构C ++中的指针分配和删除内存

来自分类Dev

c char指针的内存和全局变量

来自分类Dev

与C语言中的指针和虚拟内存的混淆

来自分类Dev

指针和虚拟内存

来自分类Dev

双指针和内存分配

来自分类Dev

Webassemly内存管理和指针

来自分类Dev

内存寻址和指针练习

来自分类Dev

指针内存分配和删除

来自分类Dev

理解C ++中双指针和单指针内存分配之间的区别的问题

来自分类Dev

指针的c ++内存分配过程

来自分类Dev

C ++内存保护指针

来自分类Dev

内存中的C和带符号字节表示