改变c中分配内存的维数
changing dimensionality of allocated memory in c
考虑定义如下的帧缓冲区数组:
static uint8_t framebuffer[num_buffers][1024];
数组被定义为每个显示缓冲区只有一个维度,因为底层硬件外围设备在我的嵌入式应用程序中需要它。然而,在代码的其他区域,通过额外的维度来处理相同的帧缓冲区将非常有利,例如:
framebuffer[buf][page][col];
我该如何做到这一点?使用实数,我希望 page 的范围为 0 到 7,col 为 0 到 127。注意:每页为 128 字节。例如,此语句的计算结果为真,因为它们将引用相同的字节:
framebuffer[0][130] == framebuffer[0][1][2]
因为 130 / 128 = 1(页面)和 130 % 128 = 2(列)。我假设我需要使用 malloc,但我未能产生正确的行为。
与其通过不同类型的数组访问数组,我强烈建议创建一个函数来 return 数组的正确元素。
uint8_t getFrameBufferItem(uint8_t framebuffer[][1024],
int i,
int j,
int k)
{
return framebuffer[i][j*128+k];
}
创建一个类似的函数来设置项目的值。
void setFrameBufferItem(uint8_t framebuffer[][1024],
int i,
int j,
int k,
uint8_t val)
{
framebuffer[i][j*128+k] = val;
}
你有几个选择。第一种是创建一个变量,该变量是 uint8_t
指针的双精度数组并执行以下操作:
static uint8_t original_framebuffer[num_buffers][1024];
static uint8_t *new_framebuffer[num_buffers][8];
int i;
for(i = 0; i < 8; i++) {
new_framebuffer[0][i] = &original_framebuffer[0][i * 128];
}
这样original_framebuffer[0][130]
指的是与new_framebuffer[0][1][2]
相同的内存位置
我建议的另一个选项并不完全是您想要的,但您可以将索引包装在宏中:
#define XY_ACCESS(_x, _y) ((_x) * 128 + (_y))
那么你会得到以下内容:
framebuffer[0][130] == framebuffer[0][XY_ACCESS(1, 2)]
您当然也可以使用函数而不是宏。
"dimensionality"不是分配内存的属性,而是数据类型。您可以通过具有不同维度的不同类型的指针访问同一内存,前提是您要注意确保整体大小和对齐方式兼容。因此,对于您的示例,您可以这样做:
static uint8_t framebuffer[numbuffers][1024];
uint8_t (*redimensioned)[8][128] = (uint8_t (*)[8][128])framebuffer;
.. 然后,例如,将第二个缓冲区的第 3 页的第 4 列归零为:
redimensioned[1][2][3] = 0;
详细说明一下,原始声明 uint8_t framebuffer[numbuffers][1024];
声明了一个数组数组(numbuffers
个 1024
uint8_t
的数组)。它会衰减为指向 1024
uint8_t
的数组的指针(或 uint8_t (*)[1024]
,也可以作为 N x 1024
二维数组访问。
我们还可以通过指向 128
uint8_t
的 8
数组的数组的指针访问原始数组的内容,这就是 uint8_t (*redimensioned)[8][128];
给我们的,我们可以将其作为 N x 8 x 128
3 维数组访问(在将其指向原始数组的内容后)。
为了让编译器满意,当我们将 redimensioned
指向 framebuffer
的内容时,我们必须强制转换它,因为指针 framebuffer
衰减到的类型不同于我们声明的指针的类型...这是 (uint8_t (*)[8][128])
在赋值中的来源(它是对 "pointer to arrays of 8 arrays of 128 uint8_t's" 的转换)。
考虑定义如下的帧缓冲区数组:
static uint8_t framebuffer[num_buffers][1024];
数组被定义为每个显示缓冲区只有一个维度,因为底层硬件外围设备在我的嵌入式应用程序中需要它。然而,在代码的其他区域,通过额外的维度来处理相同的帧缓冲区将非常有利,例如:
framebuffer[buf][page][col];
我该如何做到这一点?使用实数,我希望 page 的范围为 0 到 7,col 为 0 到 127。注意:每页为 128 字节。例如,此语句的计算结果为真,因为它们将引用相同的字节:
framebuffer[0][130] == framebuffer[0][1][2]
因为 130 / 128 = 1(页面)和 130 % 128 = 2(列)。我假设我需要使用 malloc,但我未能产生正确的行为。
与其通过不同类型的数组访问数组,我强烈建议创建一个函数来 return 数组的正确元素。
uint8_t getFrameBufferItem(uint8_t framebuffer[][1024],
int i,
int j,
int k)
{
return framebuffer[i][j*128+k];
}
创建一个类似的函数来设置项目的值。
void setFrameBufferItem(uint8_t framebuffer[][1024],
int i,
int j,
int k,
uint8_t val)
{
framebuffer[i][j*128+k] = val;
}
你有几个选择。第一种是创建一个变量,该变量是 uint8_t
指针的双精度数组并执行以下操作:
static uint8_t original_framebuffer[num_buffers][1024];
static uint8_t *new_framebuffer[num_buffers][8];
int i;
for(i = 0; i < 8; i++) {
new_framebuffer[0][i] = &original_framebuffer[0][i * 128];
}
这样original_framebuffer[0][130]
指的是与new_framebuffer[0][1][2]
我建议的另一个选项并不完全是您想要的,但您可以将索引包装在宏中:
#define XY_ACCESS(_x, _y) ((_x) * 128 + (_y))
那么你会得到以下内容:
framebuffer[0][130] == framebuffer[0][XY_ACCESS(1, 2)]
您当然也可以使用函数而不是宏。
"dimensionality"不是分配内存的属性,而是数据类型。您可以通过具有不同维度的不同类型的指针访问同一内存,前提是您要注意确保整体大小和对齐方式兼容。因此,对于您的示例,您可以这样做:
static uint8_t framebuffer[numbuffers][1024];
uint8_t (*redimensioned)[8][128] = (uint8_t (*)[8][128])framebuffer;
.. 然后,例如,将第二个缓冲区的第 3 页的第 4 列归零为:
redimensioned[1][2][3] = 0;
详细说明一下,原始声明 uint8_t framebuffer[numbuffers][1024];
声明了一个数组数组(numbuffers
个 1024
uint8_t
的数组)。它会衰减为指向 1024
uint8_t
的数组的指针(或 uint8_t (*)[1024]
,也可以作为 N x 1024
二维数组访问。
我们还可以通过指向 128
uint8_t
的 8
数组的数组的指针访问原始数组的内容,这就是 uint8_t (*redimensioned)[8][128];
给我们的,我们可以将其作为 N x 8 x 128
3 维数组访问(在将其指向原始数组的内容后)。
为了让编译器满意,当我们将 redimensioned
指向 framebuffer
的内容时,我们必须强制转换它,因为指针 framebuffer
衰减到的类型不同于我们声明的指针的类型...这是 (uint8_t (*)[8][128])
在赋值中的来源(它是对 "pointer to arrays of 8 arrays of 128 uint8_t's" 的转换)。