c - 数组映射选定的内存区域

标签 c arrays pointers casting

在处理其他问题时,我需要创建一些指向任意选定内存区域的指针,以便能够查找内存值。这些实验给我带来了有趣的问题和疑问。

考虑以下代码:

//Some hypothetical memory area simulation
unsigned char data[4][4] =
{
    {0x11,0x11,0x11,0x11}, //Memory areas 0x00 - 0x03
    {0x22,0x22,0x22,0x22}, //Memory areas 0x04 - 0x07
    {0x33,0x33,0x33,0x33},
    {0x44,0x44,0x44,0x44},
};

// Structure that wraps byte array
typedef struct
{
    unsigned char TestArr1[4];
    unsigned char TestArr2[4];
    unsigned char TestArr3[4];
    unsigned char TestArr4[4];
}structure_t;

//Pointer to array of 4 chars
unsigned char (*MemLookup1)[4];

structure_t *StructLook;

int main(void)

{
    //Set both tested variables on first address of test array
    MemLookup1 = &data;
    StructLook = &data;
    //Some helpers to visualize results
    unsigned char * temp1, *temp2, *temp3, *temp4, *temp5;
    temp1 = &MemLookup1[0][0];
    temp2 = &MemLookup1[0][1];
    temp3 = &MemLookup1[0][2];
    temp4 = &MemLookup1[0][3];
    temp5 = &MemLookup1[1][0];

}

MemLookup1被声明为指向 4 个字符数组的指针(根据 THIS )。调试器下的结果令我惊讶。

临时值如下:

*temp1 = 0x11
*temp2 = 0x22
*temp3 = 0x33
*temp4 = 0x44
*temp5 = 0x11//在内存区域0x04

StructLook.TestArr10x11,0x11,0x11,0x11

StructLook.TestArr20x22,0x22,0x22,0x22

等等。

问题是:

  1. 如何记录和解释指针的“附加”维度这一特性?请注意,指针导航时使用 [n][x] 表示法,即使该指针被声明为一维数组。

  2. 为什么以这种方式定义的指针的内存对齐会使值在内存中“垂直”呈现?迭代第一个索引时,即 &(MemLookup1[1])给我们地址 MemLookup1[0] + size of element pointed by pointer而不是更自然的数组或字符本身的第二个元素。

  3. 如何创建满足我要求的数组类型指针?

  4. 最后但并非最不重要的一点:为什么当数组包裹在结构周围时它工作得很好? StructLook给了我我所需要的,对内存单元的线性查找。

编辑

Pics来自调试器。 代码是针对 C(MinGW + GDB)编译的

最佳答案

因为你的代码非常像 C,并且 gcc编译成功——尽管有警告——所以我将回答 C 案例。

首先,我确认您的 MemLookup1被声明为一个指向四个数组 unsigned char 的指针。我还观察到您的 data被声明为一个由四个数组组成的数组,每个数组四个 unsigned char ,因此 data元素的类型与 MemLookup1 类型相同指向。

现在考虑这个作业:

MemLookup1 = &data;

右侧是一个指向四个数组的指针,每个数组有四个 unsigned char ,但左侧指定一个指向四个数组 unsigned char 的指针。这些不是兼容的类型,因此您的代码不满足简单赋值运算符的操作数的约束(由 C2011 6.5.16.1/1 表示),因此您的程序的行为是未定义的。类似的情况也适用于 StructLook 的分配。正确的分配是 MemLookup1 = data , MemLookup1 = &data[0] ,或类似的。

尽管 C 语言没有定义程序的行为,但如果可以编译它,那么我们确实可以使用调试器来尝试查看某些特定运行中实际发生的情况。请注意,C 并不保证每次运行时都是相同的,甚至也不保证程序不会以某种方式与调试器不兼容,但希望是永恒的。

你就在这里跌倒了。您声称通过指针MemLookup1获得了不同的数据 View 比你通过指针 StructLook 所做的更多,但是调试器窗口图像中显示的表达式并不相似。例如,您似乎对 StructLook->TestArr1[1] 感到惊讶与 *MemLookup1[1] 的值不同,但这是可以预料的。

正如我们已经确定的,MemLookup1是一个指向四个数组的指针 unsigned charMemLookup1[1]因此指定 MemLookup1[0] 之后的数组在内存中。在本例中,调试器显示 MemLookup1StructLook都是 data 的别名,所以MemLookup1[1]是指向 data[1] 的指针,而StructLook->TestArr1data[0] 的别名。数组索引的优先级高于指针取消引用,在这种情况下,与大多数其他情况一样,数组值表达式会衰减为指向数组第一个元素的指针,因此 *MemLookup1[1]相当于 data[1][0] 。与(*MemLookup1)[1]对比,相当于data[0][1] 。另请注意 (*MemLookup1)[1] 形式的相似性以及声明形式MemLookup1 .

这与 temp1 有什么关系... temp5尚不清楚。您的调试 View 不会显示与这些相关的任何表达式。

关于c - 数组映射选定的内存区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34296534/

相关文章:

c - 带指针的 C 数组队列

c++ - 使用 Bison 的文件指针追加字符串

c# - c/c++ 类似于 c# System.ServiceModel.Channels.BufferManager

Java 数组声明中奇怪的语法

javascript - Json 格式的对象到带有新键的简单数组

c++ - C++中如何实现指向成员函数的指针?

c - 奇怪的情况 - 要求输入 100 位数字

c - 如何显示已被赋予多个值的变量的最大值? (C 编程)

javascript - 当只有一个元素时,字符串数组作为字符串传递到我的 Controller

c++ - 与使用指针通过引用传递数组混淆