سلسلة منتهية بـ null
في برمجة الحاسوب ، السلسلة المنتهية بحرف فارغ هي سلسلة أحرف تُخزَّن كمصفوفة تحتوي على الأحرف وتنتهي بحرف فارغ (حرف قيمته الداخلية صفر، ويُسمى "NUL" في هذه المقالة، وهو ليس نفسه رمز الصفر). ومن الأسماء البديلة لها سلسلة C ، نسبةً إلى لغة البرمجة C، و ASCIIZ [ 1 ] (مع أن لغة C تدعم ترميزات أخرى غير ASCII ).
يُحدد طول السلسلة بالبحث عن أول حرف فارغ (NUL). قد تكون هذه العملية بطيئة، إذ تستغرق زمنًا خطيًا (O( n )) بالنسبة لطول السلسلة. وهذا يعني أيضًا أن السلسلة لا يمكن أن تحتوي على حرف فارغ (يوجد حرف فارغ في الذاكرة، لكنه يقع بعد الحرف الأخير، وليس ضمن السلسلة نفسها).
تاريخ
تم إنتاج السلاسل النصية المنتهية بـ null بواسطة توجيهات لغات التجميع.ASCIZ الخاصة بجهاز PDP-11 وتوجيهات لغة التجميع الخاصة بـ MACRO-10 لجهاز PDP-10 . وقد سبقت هذه التوجيهات تطوير لغة البرمجة C، ولكن تم استخدام أشكال أخرى من السلاسل النصية في كثير من الأحيان.ASCIZ
في وقت تطوير لغة C (واللغات المشتقة منها)، كانت الذاكرة محدودة للغاية، لذا كان استخدام بايت واحد فقط لتخزين طول السلسلة النصية خيارًا جذابًا. البديل الشائع آنذاك، والذي يُعرف عادةً باسم "سلسلة باسكال" (أو "سلسلة ذات بادئة طولية " في المصطلحات الحديثة)، كان يستخدم بايتًا أوليًا لتخزين طول السلسلة. يسمح هذا للسلسلة باحتوائها على حرف NUL، ويجعل إيجاد الطول يتطلب عملية وصول واحدة فقط إلى الذاكرة ( زمن ثابت O(1) )، ولكنه يحد من طول السلسلة إلى 255 حرفًا. اختار مصمم لغة C، دينيس ريتشي، اتباع اصطلاح إنهاء السلسلة بحرف NUL لتجنب هذا القيد، ولأن الحفاظ على عدد الأحرف بدا، من واقع خبرته، أقل ملاءمة من استخدام مُنهي السلسلة. [ 2 ]
كان لهذا الأمر بعض التأثير على تصميم مجموعة تعليمات وحدة المعالجة المركزية . فقد احتوت بعض وحدات المعالجة المركزية في سبعينيات وثمانينيات القرن الماضي، مثل Zilog Z80 و DEC VAX ، على تعليمات مخصصة للتعامل مع السلاسل النصية ذات البادئات الطولية. ومع ذلك، مع ازدياد شيوع استخدام السلاسل النصية المنتهية بـ null، بدأ مصممو وحدات المعالجة المركزية في أخذها بعين الاعتبار، كما يتضح على سبيل المثال في قرار شركة IBM بإضافة تعليمات "مساعدة السلسلة المنطقية" إلى ES/9000 520 في عام 1992 وتعليمات سلسلة المتجهات إلى IBM z13 في عام 2015. [ 3 ]
أشار بول هينينغ كامب ، مطور نظام FreeBSD ، في مقال له في مجلة ACM Queue ، إلى انتصار السلاسل النصية المنتهية بـ null على طول 2 بايت (وليس بايت واحد) باعتباره "أغلى خطأ في بايت واحد" على الإطلاق. [ 4 ]
القيود
على الرغم من سهولة تطبيق هذا التمثيل، إلا أنه كان عرضة للأخطاء ومشاكل الأداء.
لطالما تسببت نهاية السلسلة بحرف فارغ في مشاكل أمنية . [ 5 ] فإدراج حرف فارغ في منتصف السلسلة سيؤدي إلى اقتطاعها بشكل غير متوقع. [ 6 ] ومن الأخطاء الشائعة عدم تخصيص مساحة إضافية للحرف الفارغ، مما أدى إلى كتابته في الذاكرة المجاورة. كما أن عدم كتابة الحرف الفارغ على الإطلاق كان خطأً آخر، وهو ما لم يُكتشف غالبًا أثناء الاختبار لأن كتلة الذاكرة كانت تحتوي بالفعل على أصفار. ونظرًا لتكلفة حساب طول السلسلة، لم تُكلّف العديد من البرامج نفسها عناء ذلك قبل نسخ السلسلة إلى مخزن مؤقت ذي حجم ثابت ، مما تسبب في تجاوز سعة المخزن المؤقت إذا كانت السلسلة طويلة جدًا.
يستلزم عدم القدرة على تخزين الصفر فصل البيانات النصية عن البيانات الثنائية ومعالجتها بواسطة دوال مختلفة (مع اشتراط تحديد طول البيانات في حالة الأخيرة). قد يؤدي ذلك إلى تكرار التعليمات البرمجية وظهور أخطاء عند استخدام الدالة الخاطئة.
يمكن عادةً التخفيف من مشاكل السرعة المتعلقة بإيجاد الطول عن طريق دمجها مع عملية أخرى من رتبة O( n ) على أي حال، كما هو الحال في strlcpy. ومع ذلك، فإن هذا لا يؤدي دائمًا إلى واجهة برمجة تطبيقات بديهية .
ترميز الأحرف
تتطلب السلاسل المنتهية بـ NUL عدم استخدام البايت الصفري (0x00) في أي مكان؛ لذا، لا يمكن تخزين جميع سلاسل ASCII أو UTF-8 الممكنة . [ 7 ] [ 8 ] [ 9 ] مع ذلك، من الشائع تخزين مجموعة فرعية من ASCII أو UTF-8 - أي جميع الأحرف باستثناء NUL - في السلاسل المنتهية بـ NUL. تستخدم بعض الأنظمة " UTF-8 المعدل " الذي يشفر NUL كبايتين غير صفريين (0xC0، 0x80)، مما يسمح بتخزين جميع السلاسل الممكنة. هذا غير مسموح به في معيار UTF-8، لأنه تشفير طويل جدًا ، ويُعتبر خطرًا أمنيًا. يمكن استخدام بايت آخر كنهاية للسلسلة، مثل 0xFE أو 0xFF، وهما غير مستخدمين في UTF-8.
يستخدم ترميز UTF-16 أعدادًا صحيحة ثنائية البايت، وبما أن أيًا من البايتين قد يكون صفرًا (وفي الواقع، كل بايت ثانٍ يكون كذلك عند تمثيل نص ASCII)، فلا يمكن تخزينه في سلسلة بايتات منتهية بـ NUL. مع ذلك، تُنفذ بعض اللغات سلسلة من أحرف UTF-16 ذات 16 بت ، تنتهي بـ NUL ذي 16 بت (0x0000).
التحسينات
بُذلت محاولات عديدة لجعل معالجة السلاسل النصية في لغة C أقل عرضةً للأخطاء. تتمثل إحدى الاستراتيجيات في إضافة دوال أكثر أمانًا مثل ` strdupand` و`and` strlcpy، مع إهمال استخدام الدوال غير الآمنة مثل ` getsand`. وتتمثل استراتيجية أخرى في إضافة غلاف برمجي كائني التوجه حول السلاسل النصية في لغة C بحيث لا يمكن استدعاء سوى الدوال الآمنة. ومع ذلك، لا يزال من الممكن استدعاء الدوال غير الآمنة.
تستبدل معظم المكتبات الحديثة سلاسل C ببنية تحتوي على قيمة طول 32 بت أو أكبر (أكبر بكثير مما كان يُؤخذ في الاعتبار للسلاسل ذات البادئات الطولية)، وغالبًا ما تضيف مؤشرًا آخر، وعددًا للمراجع، وحتى قيمة NUL لتسريع عملية التحويل مرة أخرى إلى سلسلة C. أصبحت الذاكرة الآن أكبر بكثير، بحيث إذا كانت إضافة 3 (أو 16، أو أكثر) بايت لكل سلسلة مشكلة حقيقية، فسيتعين على البرنامج التعامل مع عدد كبير جدًا من السلاسل الصغيرة، ما يجعل استخدام طريقة تخزين أخرى يوفر المزيد من الذاكرة (على سبيل المثال، قد يكون هناك عدد كبير جدًا من التكرارات لدرجة أن جدول التجزئة سيستخدم ذاكرة أقل). تشمل الأمثلة مكتبة قوالب C++ القياسيةstd::string ، و QtQString ، و MFCCString ، والتنفيذ القائم على لغة C CFStringمن Core Foundation، بالإضافة إلى نظيره المكتوب بلغة Objective-CNSString من Foundation ، وكلاهما من Apple. يمكن أيضًا استخدام هياكل أكثر تعقيدًا لتخزين سلاسل مثل " الحبل" .
انظر أيضاً
مراجع
- ↑ "الفصل 15 - لغة تجميع MIPS" (ملف PDF) . جامعة كارلتون . تم الاطلاع عليه بتاريخ 9 أكتوبر 2023 .
- ↑ ريتشي، دينيس م. (1996). "تطور لغة C". في: بيرجين الابن، توماس ج.؛ جيبسون الابن، ريتشارد ج. (محرران). تاريخ لغات البرمجة ( الطبعة الثانية). نيويورك: مطبعة ACM. ISBN 0-201-89502-1– عبر دار نشر أديسون-ويسلي (ريدينغ، ماساتشوستس).
- ↑ مبادئ تشغيل بنية IBM z
- ↑ كامب، بول-هينينغ (25 يوليو 2011)، "أغلى خطأ في بايت واحد"، مجلة ACM Queue ، 9 (7): 40-43 ، doi : 10.1145/2001562.2010365 ، ISSN 1542-7730 ، S2CID 30282393
- ↑ رين فورست بوبي (9 سبتمبر 1999). "مشاكل بيرل في الرسوم المتحركة الحاسوبية" . مجلة فراك . 9 (55). artofhacking.com: 7. تم الاطلاع عليه في 3 يناير 2016 .
- ↑ "حقن البايت الفارغ في PHP؟" .
- ↑ يرجو، فرانسوا (نوفمبر 2003). "UTF-8، صيغة تحويل ISO 10646" . تم الاطلاع عليه بتاريخ 19 سبتمبر 2013 .
- ↑ "جدول أحرف يونيكود/UTF-8" . تم الاطلاع عليه بتاريخ 13 سبتمبر 2013 .
- ↑ كون، ماركوس. "أسئلة وأجوبة حول UTF-8 و Unicode" . تم الاطلاع عليه بتاريخ 13 سبتمبر 2013 .
- هياكل بيانات السلاسل
