【问题标题】:Rotating an array by 180° with strides in C在 C 中以跨步将数组旋转 180°
【发布时间】:2026-01-21 12:40:02
【问题描述】:

在我更一般的上一个问题之后:How to rotate an array by ± 180° in an efficient way?

我想知道如何在 C 中使用内存视图或跨步将 M×N 数组旋转 180° 而无需复制它,仅通过索引转换。

索引映射如下:

for (i in [0:M-1], j in [0:N-1]) do
    rotated[i, N-1-j] = array[M-1-i, j]

旋转后的内存视图将在稍后的卷积产品中使用

【问题讨论】:

  • 你打算如何访问你的旋转数组?
  • 按单元格索引
  • (a) 你说你想旋转数组而不复制它,但显示一个从array 复制到rotated 的映射。如果要旋转数组,可以将第一个元素与最后一个元素交换,将第二个元素与倒数第二个元素交换,等等。这将有一半的复制内存访问。 (b) 许多现代处理器具有 SIMD 功能,可以更快地执行此操作,因此最佳答案取决于您将运行的系统以及您是否可以使用非标准 C 代码作为解决方案。
  • (c) 许多卷积使用小内核,或者至少使用比您的数组小得多的内核,旋转内核而不是旋转数据数组会更快。

标签: c arrays


【解决方案1】:

简短的回答是 C 中没有内存视图或跨步。

长答案。

问题是你基本上只有一块平坦的内存。

想象一下下面的声明int arr[3][6],这实质上意味着你有一块能够存储18个整数值的内存,所以每当你做类似int a = arr[2][3]的事情时,它基本上与int a = ((int*)arr)[2*6 + 3]相同。因此,如果您有int arr[M][N],您可以就地更改它或复制到另一个数组。内存视图在 python 中的作用可能是它为您提供了一个隐式函数来访问您的数据:

#define N 10
#define M 20

int arr[M][N];

inline int at_rotated(int size_t i, size_t j) {
  return arr[M-1-i][N-1-j];
} 

这可能不是您想要的,因为它迫使您坚持指定的维度并保持数组“全局”。

一种更通用的方法是。

struct arr_s {
  int(*at)(struct arr_s *arr, size_t, size_t);
  size_t rows;
  size_t cols;
  int *data;
};

int at(struct arr_s *arr, size_t i, size_t j) {
  if (arr->at) return arr->at(arr, i, j);
  return arr->data[i * arr->cols + j];
}

int rotated_at_(struct arr_s *arr, size_t i, size_t j) {
  return arr->data[(arr->rows - 1 - i) * arr->cols + (arr->cols - 1 - j)];
}

struct arr_s rotate(struct arr_s *arr) {
  struct arr_s res = *arr;
  res.at = rotated_at_;
  return res;
}

int main(void) {

  struct arr_s some = {
    .rows = 2,
    .cols = 3,
    .data = (int*)(int[2][3]){ { 1, 2, 3}, {4, 5, 6} },
  };

  int a = at(&some, 0, 2);

  struct arr_s rotated = rotate(&some);

  int b = at(&rotated, 0, 2);

  printf("%d %d\n", a, b);

  return 0;
}

问题是所有这些调度和东西不会很快。不过,您可以结合第一种和第二种方法。

【讨论】: