س شار [256] مقابل شار * = malloc (256 * sizeof (تشار))؛

StackOverflow https://stackoverflow.com/questions/419022

  •  03-07-2019
  •  | 
  •  

سؤال

وأشارت

وهنا شخص ما مؤخرا لي في قطعة من التعليمات البرمجية لي أنا أستخدم

char* name = malloc(256*sizeof(char));
// more code
free(name);

وكنت تحت انطباع بأن هذه الطريقة في إنشاء مجموعة مطابقة للباستخدام

char name[256];

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

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

المحلول

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

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

واختيار بين الاثنين بناء على متطلبات للذاكرة.

وإضافة (باكس):

إذا جاز لي أن أضيف إلى ذلك، نيد، معظم تطبيقات سيوفر عادة أكثر كومة من كومة (على الأقل افتراضيا). وهذا لن يهم عادة 256 بايت إلا إذا كنت بالفعل نفاد كومة أو تفعل أشياء متكررة بشكل كبير.

وأيضا، sizeof (شار) هو دائما 1 فقا لمعيار لذلك أنت لا تحتاج أن تتضاعف لزوم له. على الرغم من أن المترجم وربما تحسين بعيدا، فإنه يجعل رمز IMNSHO القبيح.

النهاية الإضافة (باكس).

نصائح أخرى

<اقتباس فقرة>   

ووأن كلا الاتجاهين يتطلب استخدام مجانا ().

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

void doit() {
    /* ... */
    /* SP += 10 * sizeof(int) */
    int a[10];
    /* ... (using a) */

} /* SP -= 10 */

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

<ع> استخدام malloc مختلفة. وسوف تأمر بعض التعسفية قطعة ذاكرة كبيرة (من مكان يسمى <م> freestore ). فإن وقت التشغيل لديها لبحث كتلة كبيرة إلى حد معقول من الذاكرة. يمكن تحديد حجم في وقت التشغيل، وبالتالي فإن المترجم عموما لا يمكن تحسين ذلك في وقت الترجمة. لأن مؤشر يمكن أن تخرج من نطاق، أو يتم نسخ حولها، وليس هناك اقتران المتأصل بين الذاكرة المخصصة، ومؤشر الذي تم تعيين عنوان الذاكرة، لذلك لا يزال تخصيص الذاكرة حتى لو كنت قد تركت وظيفة منذ فترة طويلة . لديك لدعوة مرور مجانا من العنوان الذي حصلت عليه من malloc يدويا إذا كان الوقت قد حان للقيام بذلك.

وشكلا "الأخير" من C، ودعا C99، يسمح لك لإعطاء صفائف حجم التشغيل. أي بمعنى يسمح لك أن تفعل:

void doit(int n) {
    int a[n]; // allocate n * sizeof(int) size on the stack */
}

ولكن يجب أن يكون أفضل تجنب هذه الميزة إذا لم يكن لديك سبب لاستخدامه. سبب واحد هو أنه لا المأمونة الجانب: إذا لم يكن هناك ذاكرة متوفرة بعد الآن، أي شيء يمكن أن يحدث. آخر هو أن C99 ليس محمولة جدا بين المجمعين.

وهناك احتمال ثالث هنا، وهو أن مجموعة يمكن الإعلان الخارجي إلى وظيفة، ولكن بشكل ثابت، على سبيل المثال،

// file foo.c
char name[256];

int foo() {
    // do something here.
}

وفوجئت إلى حد ما في الإجابة على سؤال آخر حول SO أن شخصا ما شعرت أن هذا غير مناسب في C. هنا انها ليست حتى ذكر، وأنا بشيء من الارتباك والدهشة (مثل "ما هم تعليم الاطفال في المدرسة في هذه الأيام؟") حول هذا الموضوع.

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

وانها المفيد التذكير كامل "أعلن" مقابل شيء "محددة" هنا. وهنا مثال

/* example.c */

char buf1[256] ;           /* declared extern, defined in data space */
static char buf2[256] ;    /* declared static, defined in data space */
char * buf3 ;              /* declared extern, defined one ptr in data space */
int example(int c) {       /* c declared here, defined on stack */
    char buf4[256] ;       /* declared here, defined on stack   */
    char * buf5 = malloc(256)]   /* pointer declared here, defined on stack */
                           /* and buf4 is address of 256 bytes alloc'd on heap */
    buf3 = malloc(256);    /* now buf3 contains address of 256 more bytes on heap */

    return 0;              /* stack unwound; buf4 and buf5 lost.      */
                           /* NOTICE buf4 memory on heap still allocated */
                           /* so this leaks 256 bytes of memory */
}

والآن في ملف مختلف تماما

/* example2.c */

extern char buf1[];             /* gets the SAME chunk of memory as from example.c */
static char buf2[256];          /* DIFFERENT 256 char buffer than example.c */
extern char * buf3 ;            /* Same pointer as from example.c */
void undoes() {
     free(buf3);                /* this will work as long as example() called first */
     return ;
}

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

وكسر أسفل بيانكم

char* name = malloc(256*sizeof(char)); // one statement
char *name; // Step 1 declare pointer to character
name = malloc(256*sizeof(char)); // assign address to pointer of memory from heap
name[2]; // access 3rd item in array
*(name+2); // access 3rd item in array
name++; // move name to item 1

والترجمة: الاسم هو الآن مؤشر إلى الطابع الذي تم تعيينه عنوان بعض الذاكرة على كومة

char name[256]; // declare an array on the stack
name++; // error name is a constant pointer
*(name+2); // access 3rd item in array
name[2]; // access 3rd item in array
char *p = name;
p[2]; // access 3rd item in array
*(p+2); // access 3rd item in array
p++; // move p to item 1
p[0]; // item 1 in array

والترجمة: اسم هو مؤشر ثابت إلى الحرف الذي يشير إلى بعض الذاكرة على كومة

في صفائف C والمؤشرات هي نفس الشيء أكثر أو أقل من ذلك. صفائف مؤشرات ثابتة للذاكرة. والفرق الرئيسي هو أنه عند استدعاء malloc كنت تأخذ الذاكرة الخاصة بك من كومة وأي ذاكرة مأخوذة من كومة يجب أن حررت من الكومة. عندما تقوم بتعريف مجموعة بحجم يتم تعيينه ذاكرة من المكدس. لا يمكنك تحرير هذه الذاكرة لأنه مصنوع مجانا لتحرير الذاكرة من الكومة. سيتم تلقائيا تحرير الذاكرة على المكدس عندما ترجع وحدة البرامج الحالية. في المثال الثاني مجانا (ع) سيكون خطأ أيضا. ص هو مؤشر مجموعة اسم على المكدس. ذلك عن طريق تحرير ص تحاول تحرير الذاكرة على المكدس.

وهذا لا يختلف عن:

int n = 10;
int *p = &n;

وسوف تحرير p في هذه الحالة يكون خطأ لأن نقطة p لن وهو المتغير على المكدس. لذلك ع حاصل على موقع الذاكرة في كومة ولا يمكن تحرير.

int *p = (int *) malloc(sizeof(int));
*p = 10;
free(p);

في هذه الحالة مجانا غير صحيحة لأن نقاط ص إلى موقع الذاكرة على كومة التي تم تخصيصها من قبل malloc.

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

وأيضا، كما شار [] وغالبا ما تستخدم في الجمل، وانها ليست فكرة سيئة للسماح للسلسلة بناء طريقة لتخصيص الذاكرة التي يحتاجها للسلسلة في السؤال، بدلا من الأمل في أن يتمكن أي وقت مضى، ودائما 256 (أو أيا كان الرقم الذي مرسوم) لن يكون كافيا.

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