سؤال

أحاول تنفيذ المصفوفات ثلاثية الأبعاد المتجاورة المخصصة ديناميكيًا في رمز C. يجب أن تكون المصفوفات متجاورة لأنني أعتمد على إخراج NetCDF من المصفوفات. الآن قمت بتكييف حل تم نشره هنا حل المكدس فوق الحل. يعمل هذا بشكل جيد لتخصيص المصفوفات بشكل ديناميكي وفهرستها ... ومع ذلك ، عندما يقوم NetCDF بإخراجها ، هناك إزاحة يبدو أنها تتوسع في حجم الفهرس الثاني (JCount). هنا هي الوظيفة المعدلة:

void*** newarray(int icount, int jcount, int kcount, int type_size)
{
  int i,j,k;
  void*** iret = (void***)malloc(icount*sizeof(void***)+icount*jcount*sizeof(void**)+icount*jcount*kcount*type_size);
  void** jret = (void**)(iret+icount);
  char* kret = (char*)(jret+icount*jcount);
  for(i=0;i<icount;i++)
  {
    iret[i] = &jret[i*jcount];
  }
  for(i=0;i<icount;i++)
  {
    for(j=0;j<jcount;j++)
    {
      jret[i*jcount+j] = &kret[i*jcount*kcount*type_size+j*kcount*type_size];
    }
  }
  return iret;
}

إذا فهمت هذه الوظيفة بشكل صحيح ، فسيتم تخصيص مساحة لـ IRET للأرصدة ثلاثية الأبعاد التي تقوم بتأليف IRET (الفهرس الأول) ، وتأليف المؤشرات ثنائية الأبعاد JRET (الفهرس الثاني) ومساحة القيم الفعلية التي تقوم بتأليف KRET. ثم يرتبط مؤشر JRET ثنائي الأبعاد بقسم صفيف ثنائي الأبعاد من IRET. ثم يتم ذلك لكرريت. ثم يشير كل عنوان لـ IRET إلى القيمة الأولى لكل قسم من قسم JRET. ثم يتم توجيه كل عنوان من JRET إلى العنوان الأول من KRET.

بالنسبة للسجل ، كان كل شيء يعمل بشكل جيد مع القيم المحددة للمعالجة المسبقة للصفائف الخاصة بي. أيضًا ، إذا استخدمت بعض عبارات printf في الكود للتحقق من أرقام المصفوفات التي تظهر عليها جميعها فهرسة بشكل صحيح ويتم تشغيل الكود بشكل صحيح ، فهو مجرد أن يكون الناتج نتيجة لتخزين الذاكرة غير المتجانسة للمصفوفات.

لدي هيكل للنموذج:

typedef struct
{
  double ***test;
} STRUCT_TYPE;

الذي أخصيته بعد ذلك باستخدام

mhd    = (STRUCT_TYPE *)  malloc(sizeof(STRUCT_TYPE));
mhd.test = (double***) newarray(101,7,101,sizeof(double));

قد تكون هذه مشكلة مع NetCDF ... لكنني أود فقط معرفة روتين التخصيص الخاص بي ليس هو المشكلة.

هل كانت مفيدة؟

المحلول

هذا في الواقع إجابة على السؤال في إجابة Lazer:

هذا يجعلني أعتقد أنه عندما يخصص C الذاكرة لمجموعة ما ، فإنه يخصص الذاكرة المستخدمة> لتخزين القيم أولاً ، فإنه يخصص الذاكرة للأشكال التي توفر بنية للمصفوفة متعددة الأبعاد.

ربما يمكن لشخص ما مسح هذا الأمر بالنسبة لي؟

هناك فرق أساسي للغاية في C بين

double arr[A][B][C];

و

double ***ptr;

على الرغم من أنه يمكن فهرسة كلاهما x[i][j][k], ، رمز الجهاز الناتج مختلف تمامًا.

double arr[A][B][C] هي مجموعة من صفيفات B صفائف من الزوجي C. عند فهرسة هذا في الكود كما arr[i][j][k], ، المترجم يترجم ذلك إلى إزاحة ((i*B + j)*C + k)*sizeof(double) بايت من بداية arr. لا توجد مؤشرات وسيطة متورطة هنا ، ولكن يجب أن تكون الأبعاد B و C معروفة للمترجم.

"Double *** Ptr" هو مؤشر إلى (بداية مجموعة من) المؤشرات إلى (بداية مجموعة من) المؤشرات إلى (بداية مجموعة من) مزدوجة. عند فهرسة هذا في الكود كما ptr[i][j][k], ، ليس لدى المترجم أي خيار سوى القيام بكل عملية فهرسة بشكل منفصل واتبع جميع المؤشرات الوسيطة. ينتج عن هذا رمز مماثل مع

temp1 = ptr[i];
temp2 = temp1[j];
result = temp2[k];

ال newarray تنحت الوظيفة من كل هذه الأبراج المكونة من كتلة واحدة من الذاكرة ، ولكن هذا غير مطلوب من قبل اللغة ولا يحتوي المترجم على العلم بأن هذا يحدث ، لذلك يتعين عليه التعامل مستقلة عن بعضها البعض.

نصائح أخرى

حسنًا ، لقد وجدت إصلاحًا ... على الرغم من أنه أكثر من شيء في الاتفاقية. عندما صممت في الأصل الكود الخاص بي ، استخدمت ببساطة توجيهًا مسبقًا لإعلان أحجام الصفيف الخاصة بي. ثم أعلنت ببساطة كل صفيف داخل الهيكل. من أجل حفظ الذاكرة ، قمت ببساطة بتمرير مؤشر إلى الهياكل إلى وظائف بلدي الفرعية. هذا يعني أنه إذا كنت سأشير إلى عنصر خارج الروتين الرئيسي () ، فقد استخدمت شيئًا مثل:

grid->x;

الآن وأشير إلى كل عنصر من عناصر x مثل

grid->x[i][j][k];

بالطبع ، عندما تحتاج وظيفة NetCDF إلى مؤشر للمتغير الذي كان سيخزنه ، مررت بها للتو

grid->x

ومع ذلك ، باستخدام وظيفة تخصيص الذاكرة الجديدة هذه ، عندما أقوم بتمرير هذا إلى وظيفة ، فأنا فعليًا أقضي العنوان الأول لمساحة الذاكرة المخصصة للمؤشرات المختلفة. في جوهرها كنت أتقدم مؤشرًا إلى العنوان الخاطئ في الذاكرة. كل ما كان علي فعله هو تغيير الحجة التي تم تمريرها إلى:

&grid->x[0][0][0]

وأحصل على إخراج الصفيف المناسب. هذا يجعلني أعتقد أنه عندما يخصص C الذاكرة لمجموعة ما ، فإنه يخصص الذاكرة المستخدمة لتخزين القيم أولاً ، ثم يخصص الذاكرة للأشكال التي توفر بنية للمصفوفة متعددة الأبعاد.

ربما يمكن لشخص ما مسح هذا الأمر بالنسبة لي؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top