سؤال

والبنيات يبدو وكأنه وسيلة مفيدة لتحليل وسائل الثنائية من البيانات (أي ملف أو حزمة شبكة). هذا على ما يرام ومدهش حتى يكون لديك صفائف حجم متغير في فقاعة. على سبيل المثال:

struct nodeheader{
        int flags;
        int data_size;
        char data[];
};

وهذا يتيح لي أن العثور على البيانات الشخصية الماضي:

nodeheader b;
cout << b.data[b.data_size-1];

ومشكلة الوجود، أريد أن يكون لديك عدة صفائف متغير طول:

struct nodeheader{
    int friend_size;
    int data_size;
    char data[];
    char friend[];
};

وأنا لا يدويا تخصيص هذه الهياكل. لدي ملف مثل ذلك:

char file_data[1024];
nodeheader* node = &(file_data[10]);

وكما أحاول تحليل ملف ثنائي (أكثر تحديدا ملف فئة). لقد كتبت التنفيذ في جاوة (والتي كانت مهمة صفي)، لا أفعله نسخة الشخصية في C ++ وكان يأمل في الحصول على الفور دون الحاجة إلى إرسال 100 خط من التعليمات البرمجية. أي أفكار؟

وشكرا، ستيفان

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

المحلول

وأنت لا يمكن أن يكون لديك عدة صفائف متغير الحجم. كيف ينبغي للمترجم في وقت الترجمة يعرف أين [] يقع صديق؟ موقع صديق يعتمد على حجم البيانات [] وحجم البيانات غير معروف في وقت الترجمة.

نصائح أخرى

وهذا هو بناء خطير جدا، وأنصح ضدها. يمكنك تضمين فقط مجموعة متغيرة الطول في البنية عندما يكون العنصر الأخير، وعند القيام بذلك، لديك للتأكد من تخصيص ذاكرة كافية، منها مثلا:

nodeheader *nh = (nodeheader *)malloc(sizeof(nodeheader) + max_data_size);

وما تريد القيام به هو مجرد استخدام المصفوفات العادية المخصصة حيوي:

struct nodeheader
{
  char *data;
  size_t data_size;
  char *friend;
  size_t friend_size;
};

nodeheader AllocNodeHeader(size_t data_size, size_t friend_size)
{
  nodeheader nh;
  nh.data = (char *)malloc(data_size);  // check for NULL return
  nh.data_size = data_size;
  nh.friend = (char *)malloc(friend_size);  // check for NULL return
  nh.friend_size = friend_size;

  return nh;
}

void FreeNodeHeader(nodeheader *nh)
{
  free(nh->data);
  nh->data = NULL;
  free(nh->friend);
  nh->friend = NULL;
}

وأنت لا تستطيع - على الأقل ليس بالطريقة البسيطة التي كنت تحاول. مجموعة unsized في نهاية هيكل هي في الأساس إزاحة إلى نهاية البنية، مع عدم وجود طريقة البناء في العثور على نهاية.

ويتم تحويل جميع الحقول لإزاحة رقمية في وقت الترجمة، لذلك هم بحاجة إلى أن يكون محسوب في ذلك الوقت.

والأجوبة حتى الآن هي على محمل الجد الإفراط في تعقيد مشكلة بسيطة. Mecki هو الصحيح عن السبب في أنه لا يمكن القيام به بالطريقة التي تحاول أن تفعل ذلك، ولكن يمكنك أن تفعل ذلك بطريقة مماثلة جدا:

struct nodeheader
{
    int friend_size;
    int data_size;
};

struct nodefile
{
    nodeheader *header;
    char *data;
    char *friend;
};

char file_data[1024];

// .. file in file_data ..

nodefile file;
file.header = (nodeheader *)&file_data[0];
file.data = (char *)&file.header[1];
file.friend = &file.data[file->header.data_size];

لماذا تقومون به تحتاج إلى ترميز / فك لتنسيق. فك يأخذ البيانات الخام ويملأ الهيكل الخاص (في الحالة الخاصة بك تخصيص مساحة لنسخة من كل قسم من البيانات)، وفك يكتب ثنائي الخام.

و(كان 'استخدام الأمراض المنقولة جنسيا :: ناقلات')

وتحرير:

في قراءة ردود الفعل، وافترض أن توسيع جوابي. يمكنك تناسب بشكل فعال اثنين من صفائف طول متغير في الهيكل الخاص على النحو التالي، وسوف تفرج التخزين بالنسبة لك تلقائيا عندما file_data يخرج من نطاق:

struct nodeheader {
    std::vector<unsigned char> data;
    std::vector<unsigned char> friend_buf; // 'friend' is a keyword!
    // etc...
};

nodeheader file_data;

والآن file_data.data.size ()، وما إلى ذلك يتيح لك طول وووfile_data.data [0] يعطيك مؤشر الخام إلى البيانات إذا كنت في حاجة إليها.

وسيكون لديك لملء بيانات الملف من ملف مجزأة - قراءة طول كل العازلة، ندعو تغيير حجم () على ناقلات جهة، ثم قراءة في البيانات. (هناك طرق للقيام بذلك قليلا أكثر كفاءة. وفي سياق ملف القرص I / O، أفترض أنه لا يهم).

تقنية

وبالمناسبة OP هي غير صحيحة حتى بالنسبة له حالة "الجميلة ومدهش"، على سبيل المثال مع VLA واحد فقط في نهاية المطاف.

char file_data[1024];
nodeheader* node = &(file_data[10]);

وهناك ما يضمن أن file_data يتم محاذاة بشكل صحيح لنوع nodeheader. تفضل الحصول على file_data بواسطة malloc () - الذي يضمن للعودة مؤشر الانحياز لأي نوع - أو آخر (أفضل) يعلن المخزن المؤقت ليكون من النوع الصحيح في المقام الأول:

struct biggestnodeheader {
    int flags;
    int data_size;
    char data[ENOUGH_SPACE_FOR_LARGEST_HEADER_I_EVER_NEED];
};

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