用于在C中模拟访问二维数组的宏

Rob*_*ert 11 c opencl multidimensional-array

OpenCL仅允许使用C99规范访问单维数组.然而我的问题是二维的,我在主机端使用二维数组

我不想通过计算索引使我的代码可读性降低,而是想使用C宏来获取元素A[i][j].不幸的是,我在这方面做得很差,而且对C的经验也不多.我想我对如何做到这一点有了一般的想法,但如果有人可以批评,我将不胜感激.

它会是这样的:

#define 2d_access(u, y, x) (u[y][x])
Run Code Online (Sandbox Code Playgroud)

其中u是矩阵,y是行,x是列,宏将返回值 u[y][x]

矩阵是静态分配的,因此宏将具有WIDTH组件.

#define 2d_access(u, y, x) (u[y * WIDTH] + x])
Run Code Online (Sandbox Code Playgroud)

Chr*_*utz 7

由于到目前为止所有的答案都依赖于恒定的宽度,这里是任意宽度列的(重量级)解决方案:

#define matrix_type(t) struct { size_t width; t array[]; }

#define matrix_alloc(t, w, h) malloc(offsetof(matrix_type(t), array[(w) * (h)]))

#define matrix_init(m, t, w, h) \
  matrix_type(t) *m = matrix_alloc(t, w, h); \
  if(!m) matrix_alloc_error(); else m->width = (w);

#define matrix_index(m, w, h) m->array[m->width * (w) + (h)]

// redefine if you want to handle malloc errors
#define matrix_alloc_error()
Run Code Online (Sandbox Code Playgroud)

只需释放数组即可free.

当然,您也可以为高度添加一个字段,并进行边界检查等.您甚至可以将它们作为实际函数编写,或者使用宏来自动声明struct类型,这样您就不必struct为所有内容使用匿名类型.如果你需要它在堆栈上,你可以alloca以便携性为代价.

如果您有一个恒定的矩阵大小,您可以使用一些投射黑客来实现"本机"2D索引(通过[]运算符):

#define CAT_(x, y) x##y
#define CAT(x, y) CAT_(x, y)

#define MANGLE(x) CAT(x, _hidden_do_not_use_0xdeadbeef_)

#define matrix_init(m, t, w, h) \
  t MANGLE(m)[(w) * (h)]; \
  t (*m)[(w)] = (void *)MANGLE(m);

// because of the funky typing, `m[0][1]` does what you'd expect it to.
Run Code Online (Sandbox Code Playgroud)

请注意,与其他解决方案不同,这会创建第二个变量,这可能不是很干净,但我认为我使用了非常清晰的修改方法,所以它不会妨碍实践.


Jer*_*man 6

更简洁的是为你正在使用的每个数组定义一个宏,这样你就可以使它看起来像2D数组访问.因此,给定数组A,您将定义:

#define A(r, c) (A[(r)*WIDTH + (c)])
Run Code Online (Sandbox Code Playgroud)

请注意替换值周围的括号.这处理替换是表达式的情况,例如A(i + 1, j).没有括号,这会扩展到A[i + 1*WIDTH + j],这不是你想要的:

A[i + 1*WIDTH + j] = A[WIDTH + i + j] != A[(i + 1)*WIDTH + j]
Run Code Online (Sandbox Code Playgroud)

为了避免第二个参数出现同样的问题,两者都包含在替换文本的括号中.


Rud*_*uis 2

不批评,你已经给出了解决方案:

#define access_2d(u, y, x) (u[(y) * WIDTH + (x)])
Run Code Online (Sandbox Code Playgroud)

好吧,也许我的想法不同,但我会把它定义为

// x before y
#define access_2d(u, x, y) (u[(y) * WIDTH + (x)])
Run Code Online (Sandbox Code Playgroud)

但这并不是更好,只是一种偏好。