如何填充二维数组C++的每一行



我开始在嵌入式设备的上下文中学习C++和C,最近我开始制作自己的库,以稍微清理我的代码。将二维数组传递给函数时遇到问题。问题如下:

uint8_t cardSectors[8][16];
cardsClient.readDataBlocks(uid, uidLength, *cardSectors, 8, 16);

正如您所看到的,我正在传递cardSectors作为指向数组的指针。稍后,在读取卡片的功能中,我将使用将卡片数据写入指针

mifareclassic_ReadDataBlock(currentBlock, &cardSectors[currentBlock]);

它起作用了!我可以使用:&cardSectors[currentBlock]读取数据。

但问题是。从原始变量uint8_t cardSectors[8][16]中读取数据怎么样?无论我做了什么,我都无法获取我想要的数据。我不知道我是不是真的没有保存这些数据,还是其他地方出了问题。基本上这是一个调用堆栈:

uint8_t cardSectors[8][16];
cardsClient.readDataBlocks(uid, uidLength, *cardSectors, blocks, blockSize);
Serial.println("Do something with this data!");

在执行readDataBlocks之后,如何访问这些数据?

在C++中,可能是最简单的

#include <vector>
template <class T>
using Arr2D = std::vector<std::vector<T>>;

并传递这种类型。

由于C仅略高于汇编语言的水平,缺乏模板和其他方便的概念,因此处理2D数组的一种方法是使用线性内存块,并使用ìndex = row * ncols + col等公式计算内存中的索引。这为您节省了一些构建和清理指向某个结构的指针数组的工作,而且与在堆上单独分配每一行相比,它还提供了更好的缓存位置。

typedef struct Arr2D_tag {
void* data;
size_t element_size;
size_t nrows;
size_t ncols;
} Arr2D_t;
void* arr2d_at(Arr2D_t *array, size_t row, size_t col) {
if (NULL == array) return NULL;
if (NULL == array->data) return NULL;
if (row >= array->nrows) return NULL;
if (col >= array->ncols) return NULL;
size_t index = row * array->ncols + col;
return (char*)array->data + array->element_size * index;
}

再加上通常的C风格的狂野选角,达到你所期望的类型。您可以进一步完善这一点,方法是为事物提供一个按类型的外观(一个函数指针结构,用于对特定类型的数组进行操作,用一些预处理器宏或其他东西构建(。它看起来仍然很难看,但使用起来可能更方便一些。

如果你只有固定大小的矩阵,比如计算机图形学中经常使用的3x3或4x4,你可以选择使用std::array来代替第一个给定的C++版本,这样你就不必使用堆,并且具有与C版本相同的缓存位置:

#include <array>
template <size_t NROW, size_t NCOL>
using Arr2D_f32 = std::array<std::array<float,NCOL>, NROW>;
// ad lib for other types, e.g.
template <size_t NROW, size_t NCOL>
using Arr2D_f64 = std::array<std::array<double,NCOL>, NROW>;

一旦你有了这些类型,填充它们就很容易了:

void populate_my_array2d(Arr2D_size_t<7,13>& a) {
size_t value = 1;
for (auto& row : a) {
for (auto& col : row) {
col = value++;
}
}
}

在C型情况下,由于底层存储器只是一个1d阵列,因此只需填充对于具有单个值的矩阵,只需要1个循环,而不需要2个嵌套循环。这里是一般情况:

#include <stdbool.h>
bool populate_my_array( Arr2D_t * array, const void* value) {
if (NULL == array) return false;
for (size_t r = 0; r < array->nrows; r++) {
for (size_t c = 0; c < array->ncols; c++) {
void* cell = arr2d_at(array,r,c);
if (NULL != cell) {
memcpy(cell,value,array->element_size);
} else {
return false;
}
}
}
return true;
} 

最新更新