如何在预先分配的内存上指向2D / 3D空间

时间:2015-09-04 07:51:18

标签: c arrays pointers memory memory-management

我内存优化了我用于嵌入式使用的代码。它运行良好,但结果是我获得了大量的1D,2D和3D mallocs,并在函数中间释放,从而减慢了执行时间。

由于几个原因,我决定修改我的方式。我想在执行开始时用一个malloc分配所有可用的内存,只需指向每个数组所需的正确内存空间。

有关信息,我现在在x86上执行此操作,因此我没有任何内存空间问题。我用这种方式声明我的数组:

    LinearLayout ParentLayout = (LinearLayout) findViewById(R.id.parentLayout);

LinearLayout childLayout = new LinearLayout(MainActivity.this);
childLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 200));
childLayout.setBackgroundColor(Color.parseColor("#0F0"));
childLayout.setPadding(10, 10, 10, 10);
//defined in Xml
ParentLayout.addView(childLayout);


TextView textView1 = new TextView(MainActivity.this);
LinearLayout.LayoutParams tvParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
textView1.setLayoutParams(tvParams);
textView1.setText("Offers");
textView1.setBackgroundColor(Color.parseColor("#FF0000"));
textView1.setPadding(0, 5, 0, 10); // in pixels (left, top, right, bottom)

Button btnAB= new Button(MainActivity.this);
LinearLayout.LayoutParams btnParams = new LinearLayout.LayoutParams(40,40); //width:40dp and height:40dp
btnAB.setLayoutParams(btnParams);
final int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
    btnAB.setBackgroundDrawable( getResources().getDrawable(R.drawable.icon) );
} else {
    btnAB.setBackground( getResources().getDrawable(R.drawable.icon));
}
btnAB.setClickable(false);
childLayout.removeAllViews();
childLayout.addView(textView1);
childLayout.addView(btnAB);

虽然它适用于我的1D指针,但它为我的2D指针声明返回了一个段错误。我检查了我的偏移量,它们与内存指针相比很好。由于我没有这种方式来表达我的指示,也许我在这里误解了一些东西所以如果有人可以向我解释这个技术的更多信息,我会很高兴的!

2 个答案:

答案 0 :(得分:2)

您将p2声明为指向指针数组的指针,而不是指向平面二维数组的指针。你也是(为了清晰起见而编辑)用垃圾整数初始化p2,然后将其强制转换为指针并解除引用。

已修改为添加示例代码:

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

/* Boilerplate to turn this into a MWE: */
#define MYSIZE  1024U
typedef double elem_t;
static const size_t p1_offset = 0, p2_offset = 512;

/* Our buffer will hold W 1d elements and X*Y 2d elements. */
#define W   64U
#define X   32U
#define Y   2U
typedef struct {
  elem_t array1[W];
  elem_t array2[X][Y];
} spaces_t;

/* Test driver: */
int main(void)
{
/* sizeof(unsigned char) is defined as 1.  Do you mean to allocate an
 * array of MYSIZE bytes or MYSIZE elements of type?
 */
  spaces_t * const memory = malloc(sizeof(spaces_t));
  if (!memory) {
    perror("malloc");
    exit(EXIT_FAILURE);
  }

  elem_t* p1 = memory->array1;
  elem_t* p2 = (elem_t*)(memory->array2);

/* Never cast a pointer to int.  It's not even legal.
 * Why does this assertion succeed?  Why are memory and bad_idea
 * equal, but memory+1 and bad_idea+1 different by the size of both
 * of our arrays combined, minus one byte?
 */
  const uintptr_t bad_idea = (uintptr_t)memory;
  assert( (uintptr_t)(memory+1) - (bad_idea+1) == sizeof(spaces_t) - 1 );

/* Let’s initialize all the arrays.  No segfaults? */
  size_t i,j;

  for (i = 0; i < W; ++i) {
    *p1 = (elem_t)i;
    assert( memory->array1[i] == *p1 );
    ++p1;
  }

/* This is a lot faster when X is a power of 2: */
  for (i = 0; i < X; ++i)
    for ( j = 0; j < Y; ++j) {
      *p2 = (elem_t)(100*i + j);
      assert( memory->array2[i][j] == *p2 );
      ++p2;
    }

  return EXIT_SUCCESS;
}

答案 1 :(得分:0)

问题是type** p2;是指向指针的指针,它与2D数组无关。

相反,声明指向2D数组的指针:

type (*p2)[x][y];

如果您不想将2D数组取消引用为(*p2)[i][j],那么只需在声明中删除最里面的维度:

type (*p2)[y];

现在您可以将2D数组取消引用为p2[i][j]。这个技巧有效,因为p2[i]基于指向类型(j类型项的数组)为您提供指针算法,与任何其他指针相同。

从指针到(signed)int的强制转换也是模糊和不安全的。对于执行此操作的代码中的每个案例,请保留char类型,计算偏移量,然后将其强制转换为(void*)。例如:

p2 = (void*)(memory + p2_offset);