الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

اخترنا لك(3): تحسين حجم ذاكرة لاعضاء الفئة بترتيب الاعلان عن المتغيرات

بدأه محمد عودة في 10 سبتمبر 2012 · 2 رد · 1,166 مشاهدة · في قسم المواضيع الهامة في قسم السي /سي++
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله

مرحبا بكم في أخترنا لك(3)

الفهرس الرئيس لــ سلسلة أخترنا لك فى سي++

3.تحسين حجم ذاكرة لاعضاء الفئة بترتيب الاعلان عن المتغيرات

أن حجم size يمكن ان يتغير ليس بزيادة عدد الاعلان عن المتغيرات الاعضاء ولكن فقط بتغيير ترتيبهم فى الفئة:

struct A
{
 bool a;
 int b;
 bool c;
}; /*ان حجم هيكل البيانات == 12 بايت*/

على الجهاز الخاص بي فأن sizeof (A) يساوي 12 بايت . قد تكون هذة النتيجة مفاجئة لأن الحجم الاجمالى لــ A يساوي 6 بايت اى 1+4+1 = بايت. السؤال الآن من إين آتت الــ 6 بايت الاخري؟ الاجابة ان المترجم يدرج 3 بايت كمحاذاة بعد كل متغير عضو بولوني bool حتي يجعل موقعة محاذي فى الــ 4 بايت. بأمكانك تقليل حجم هيكل البيانات بتنظيم المتغيرات الاعضاء كالتالي:

struct B
{
 bool a;
 bool c;
 int b;
}; // الآن حجم B يساوي 8 بايت فقط أى مربعين من الذاكرة كل واحد مكون من 4 بايت

فى هذة الحالة فأن المترجم بدرج 2 بايت محاذاة بعد المتغير العضو c . لان حجم b يساوي 4 بايت اي انها تساوي عدد 1 متغير من نوع word بمقاييس لغة المعالج(الاسمبلي) اذا لاتحتاج الى اى بايت اضافي لضبط المحاذاة.

الكود والمخرجات:

#include <iostream>
using namespace std;

struct A {
	bool a;
	int b;
	bool c;
}; /*sizeof (A) == 12*/

struct B {
	bool a;
	bool c;
	int b;
}; // sizeof (B) == 8

int main() {
	struct A a;
	struct B b;
	cout << "Size of A: " << sizeof (a) << endl;
	cout << "Size of B: " << sizeof (b) << endl;
	return 0;
}

المخرجات:

Size of A: 12
Size of B: 8

هل مر على احدكم فكرة متعلقة بتحسين استخدام الذاكرة؟

والى لقاء فى تلميح واخترنا لك جديدة ان شاء الله

تم تعديل هذه المشاركة بواسطة محمد عودة في 17 سبتمبر 2012 في 09:24

2

post-15367-027053900%201340345097.gifpost-15367-087183200%201340344597.gif
post-247365-0-10080400-1379403554_thumb.

#2

جميل جداً ... في الحقيقة مر معي شيء مشابه بعض الشيء ..عن إضافة بايتات غير فعالة للمحاذاة ...

وذلك في ملفات الBMP حيث تكون الخريطة النقطية من مضاعفات الرقم 4 دائماً .. حتى لو كانت عرض الصورة غير ذلك ..

والسبب هو ما ذكرتَه أخي الكريم عن بايتات المحاذاة... يمكنك هذا الموضوع للمزيد عن BMP ...

تحياتي لك ... جزاك الله خيراً

#3

هناك طريقة أخرى لتغيير محاذات عناصر البنية في الذاكرة دون تغيير العناصر في الملف وذلك عن بالطلب من المُصرف أن يجعل المحاذاة بايت واحد بدلاً من أربع بايتات, أو أي حجم تريد ,عن طريق الموجة pack :

#include <stdio.h>

typedef struct _Pack4 {
    unsigned int member4bytes;
    char member5bytes[3];
    unsigned short member2bytes;
} Pack4;

#pragma pack(1)
typedef struct _Pack1 {
    unsigned int member4bytes;
    char member5bytes[3];
    unsigned short member2bytes;
} Pack1;
#pragma pack()

int main(int argc, char **argv)
{

    printf("Size of Pack4 = %d\n", sizeof(Pack4));
    printf("Size of Pack1 = %d\n", sizeof(Pack1));

    return 0;
}

سيعطي البرنامج :

Size of Pack4 = 12
Size of Pack1 = 9

رغم أنّ هذه توفر لك بايتات قليلة الا أنه سيقلل من أداء المعالج , فنقل أربع بايتات دفعة واحدة أسهل على المعالج ولهذا ترى الرقم دائماً من مضاعفات الأربعة.

هناك مجال يشيع فيه تغيير محاذاة عناصر البنية في الذاكرة وهو مجال صيغ وبنية الملفات. إنظر لهذا المثال لإنشاء صيغة ملف بسيطة خاصة بك إسمها bfile وبنيتها:

magic : أربع بايتات تميز هذا الملف.

age : أربع بايتات للعمر.

name : وتقبل حتى 255 بايت للإسم .

وقراءتها والكتابة إليها :

/**
 * @file bfile.h
 **/

#ifndef __BFILE_H__
#define __BFILE_H__

#pragma pack(1)
typedef struct _BFileObject {
    char magic[4];
    unsigned int age;
    char name[255];
} BFileObject;
#pragma pack()

#ifdef __cplusplus
extern "C" {
#endif

int bfile_init(BFileObject *bfile);
int bfile_read(BFileObject *bfile, char *infile);
int bfile_write(BFileObject *bfile, char *outfile);
char *bfile_get_name(BFileObject *bfile);
unsigned int bfile_get_age(BFileObject *bfile);
int bfile_set_name(BFileObject *bfile, char *name);
int bfile_set_age(BFileObject *bfile, unsigned int age);

#ifdef __cplusplus
};
#endif

#endif

/**
 * @file bfile.h
 **/

#include <stdio.h>
#include <string.h>

#include "bfile.h"

int bfile_init(BFileObject *bfile)
{
    memset(bfile, 0, sizeof(BFileObject));
    char magic[4] = {'M', 'r', '.', 'B'};
    memcpy(&bfile->magic[0], &magic[0], 4);
    return 0;
}

int bfile_read(BFileObject *bfile, char *infile)
{
    FILE *file;
    if( (file = fopen(infile, "r") ) == NULL)
        return -1;

    fread(bfile, sizeof(BFileObject), 1, file);
    fclose(file);

    return 0;
}

int bfile_write(BFileObject *bfile, char *outfile)
{
    FILE *file;
    if( (file = fopen(outfile, "w") ) == NULL)
        return -1;

    fwrite(bfile, sizeof(BFileObject), 1, file);
    fclose(file);

    return 0;
}

char *bfile_get_name(BFileObject *bfile)
{
    return &bfile->name[0];
}

unsigned int bfile_get_age(BFileObject *bfile)
{
    return bfile->age;
}

int bfile_set_name(BFileObject *bfile, char *name)
{
    if( strlen(name) >= 255 )
        return -1;
    memcpy(&bfile->name[0], name, strlen(name));
    return 0;
}

int bfile_set_age(BFileObject *bfile, unsigned int age)
{
    bfile->age  = age;
    return 0;
}

/**
 * @file main.c
 **/

#include <stdio.h>
#include "bfile.h"

int main(int argc, char **argv)
{
    BFileObject bfile1;
    BFileObject bfile2;

    /* هيئ كائن جديد من BFileObject */
    bfile_init(&bfile1);
    /* ضع الإسم */
    bfile_set_name(&bfile1, "Barakat");
    /* ضع العمر */
    bfile_set_age(&bfile1, 21);
    /* أنشئ ملف جديد إسمه وإكتب المعلومات فيه */
    bfile_write(&bfile1, "example.b");


    /* أنشئ كائن آخر */
    bfile_init(&bfile2);
    /* إقرأ ذالك الملف الذي كتبناه للتو */
    bfile_read(&bfile2, "example.b");

    printf("Name: %s\n", bfile_get_name(&bfile2));
    printf("Age: %u\n", bfile_get_age(&bfile2));

    return 0;
}

الملف الناتج :

post-231926-078861100 1347300473_thumb.p

لاحظ أنه لايلزمنا مع هذه الطريقة كتابة كود طويل ومعقد لمعالجة الملف, فقط نقرأ من بنية ونكتب لبنية.

المرفقات
bfile.png

تم تعديل هذه المشاركة بواسطة Mr.B في 10 سبتمبر 2012 في 21:25

3

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…