تحويل النوع

في علوم الحاسوب ، يُعدّ تحويل الأنواع [ 1 ] [ 2 ] ، وتحويل الأنواع [ 1 ] [ 3 ] ، وإجبار الأنواع [ 3 ] ، وتلاعب الأنواع [ 4 ] [ 5 ] طرقًا مختلفة لتغيير تعبير من نوع بيانات إلى آخر. ومن الأمثلة على ذلك تحويل قيمة عددية صحيحة إلى قيمة عددية عشرية أو تمثيلها النصي كسلسلة نصية ، والعكس صحيح. يمكن لتحويلات الأنواع الاستفادة من بعض خصائص التسلسلات الهرمية للأنواع أو تمثيلات البيانات . ومن الجوانب المهمة لتحويل الأنواع ما إذا كان يحدث ضمنيًا (تلقائيًا) أو صريحًا [ 1 ] [ 6 ] ، وما إذا كان تمثيل البيانات الأساسي يُحوّل من تمثيل إلى آخر، أو يُعاد تفسير تمثيل معين على أنه تمثيل لنوع بيانات آخر [ 6 ] [ 7 ] . وبشكل عام، يمكن تحويل كل من أنواع البيانات الأولية والمركبة .

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

في معظم لغات البرمجة، يُستخدم مصطلح " التحويل" للدلالة على التحويل الضمني ، سواءً أثناء الترجمة أو أثناء التشغيل . على سبيل المثال، في تعبير يجمع بين الأعداد الصحيحة والأعداد العشرية (مثل 5 + 0.1)، يقوم المترجم تلقائيًا بتحويل التمثيل الصحيح إلى تمثيل عشري حتى لا تُفقد الكسور. أما التحويلات الصريحة للأنواع، فتُشار إليها إما بكتابة شيفرة إضافية (مثل إضافة مُعرّفات الأنواع أو استدعاء إجراءات مُدمجة ) أو ببرمجة إجراءات تحويل ليستخدمها المترجم عندما يتوقف بسبب عدم تطابق الأنواع.

في معظم اللغات الشبيهة بلغة ALGOL ، مثل باسكال ، وموديولا-2 ، وآدا ، ودلفي ، يُعدّ التحويل والتحويل إلى نوع بيانات مفهومين مختلفين تمامًا. في هذه اللغات، يشير التحويل إلى تغيير قيمة ما، ضمنيًا أو صراحةً، من تنسيق تخزين نوع بيانات إلى آخر، على سبيل المثال، من عدد صحيح 16 بت إلى عدد صحيح 32 بت. قد تتغير متطلبات التخزين نتيجةً للتحويل، بما في ذلك احتمال فقدان الدقة أو اقتطاع البيانات. أما التحويل إلى نوع بيانات ، فيشير إلى تغيير تفسير نمط البتات الذي يُمثّل قيمة ما من نوع إلى آخر. على سبيل المثال، يمكن التعامل مع 32 بتًا متجاورًا كمصفوفة من 32 قيمة منطقية، أو سلسلة نصية من 4 بايت، أو عدد صحيح غير مُوقّع 32 بت، أو قيمة فاصلة عائمة أحادية الدقة وفقًا لمعيار IEEE. ولأن البتات المُخزّنة لا تتغير أبدًا، يجب على المبرمج معرفة التفاصيل الدقيقة، مثل تنسيق التمثيل، وترتيب البايتات، ومتطلبات المحاذاة، لإجراء التحويل إلى نوع بيانات بشكل صحيح.

في عائلة لغات C ولغة ALGOL 68 ، يشير مصطلح cast عادةً إلى تحويل صريح للنوع (مقارنةً بالتحويل الضمني)، مما يُسبب بعض الغموض حول ما إذا كان هذا إعادة تفسير لنمط بت أو تحويلًا حقيقيًا لتمثيل البيانات. والأهم من ذلك، تعدد الطرق والقواعد التي تُطبق على نوع البيانات (أو الفئة) التي يُحددها المؤشر، وكيفية تعديل المُصرّف لهذا المؤشر في حالات مثل وراثة الكائنات (الفئات).

التحويل الصريح في لغات مختلفة

آدا

توفر لغة Ada دالة مكتبة عامة باسم Unchecked_Conversion. [ 8 ]

لغات شبيهة بلغة C

تحويل النوع الضمني

التحويل الضمني للأنواع، المعروف أيضاً بالتحويل القسري أو التلاعب بالأنواع ، هو تحويل تلقائي للأنواع يقوم به المترجم . تسمح بعض لغات البرمجة للمترجمات بتوفير التحويل القسري، بينما تشترطه لغات أخرى.

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

double d ; long l ; int i ;إذا كان ( d > i ) { d = i ; }إذا كان ( i > l ) { l = i ; }إذا كان ( d == l ) { d *= 2 ; }

على الرغم من أن d و l و i تنتمي إلى أنواع بيانات مختلفة، إلا أنها تُحوّل تلقائيًا إلى أنواع بيانات متطابقة في كل مرة تُجرى فيها مقارنة أو عملية إسناد. يجب استخدام هذا السلوك بحذر، إذ قد تنشأ عواقب غير مقصودة. قد تُفقد البيانات عند تحويل التمثيلات من أعداد عشرية إلى أعداد صحيحة، حيث تُقتطع الأجزاء الكسرية من القيم العشرية (تُقرّب نحو الصفر). في المقابل، قد تُفقد الدقة عند تحويل التمثيلات من أعداد صحيحة إلى أعداد عشرية، لأن نوع البيانات العشري قد لا يتمكن من تمثيل جميع القيم الممكنة لنوع بيانات صحيح بدقة. على سبيل المثال، قد يكون نوع البيانات IEEE 754 أحادي الدقة، والذي لا يمكنه تمثيل العدد الصحيح 16777217 بدقة، بينما يستطيع نوع البيانات الصحيح 32 بت ذلك. قد يؤدي هذا إلى سلوك غير بديهي، كما هو موضح في الكود التالي:float

#include <stdio.h>int main ( void ) { int my_int = 16777217 ; float my_float = 16777216.0 ; printf ( "العدد الصحيح هو: %d \n " , my_int ); printf ( "العدد العشري هو: %f \n " , my_float ); printf ( "تساويهما: %d \n " , my_int == my_float ); }

في المترجمات التي تنفذ الأعداد العشرية بدقة أحادية وفقًا لمعيار IEEE، والأعداد الصحيحة بدقة 32 بت على الأقل، سيعطي هذا الكود هذه المخرجات الغريبة:

العدد الصحيح هو: 16777217 القيمة العائمة هي: 16777216.000000 مساواتهما: 1

لاحظ أن الرقم 1 يُمثل المساواة في السطر الأخير أعلاه. هذا السلوك غير المعتاد ناتج عن تحويل ضمني من نوع i_valueإلى نوع float عند مقارنته بـ f_value. يؤدي هذا التحويل إلى فقدان الدقة، مما يجعل القيم متساوية قبل المقارنة.

أهم النقاط المستفادة:

  1. floatintيؤدي إلى الاقتطاع ، أي إزالة الجزء الكسري.
  2. doubleيؤدي إلى floatتقريب الرقم.
  3. longيؤدي ذلك إلى intإسقاط البتات الزائدة ذات الرتبة الأعلى.
نوع العرض الترويجي

يُعدّ ترقية النوع حالةً خاصةً من حالات التحويل الضمني للأنواع، حيث يُحوّل الكائن تلقائيًا إلى نوع بيانات آخر يُمثّل مجموعةً فرعيةً من النوع الأصلي. تُستخدم الترقيات عادةً مع الأنواع الأصغر من النوع الأصلي لوحدة الحساب والمنطق (ALU) في النظام المستهدف، قبل إجراء العمليات الحسابية والمنطقية، لجعل هذه العمليات ممكنة، أو أكثر كفاءةً إذا كانت وحدة الحساب والمنطق قادرةً على التعامل مع أكثر من نوع. تُجري لغتا C وC++ هذه الترقية للكائنات من أنواع Boolean وcharacter وwidcharacter وenumeration وshort integer، حيث تُرقّى إلى int، وللكائنات من نوع float، حيث تُرقّى إلى double. على عكس بعض تحويلات الأنواع الأخرى، لا تُؤدّي الترقيات أبدًا إلى فقدان الدقة أو تعديل القيمة المُخزّنة في الكائن.

في لغة جافا :

int x = 3 ; double y = 3.5 ; System.out.println ( x + y ) ; // سيكون الناتج 6.5

تحويل النوع الصريح

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

double a = 3.3 ; double b = 3.3 ; double c = 3.4 ;int result = static_cast <int> ( a ) + static_cast <int> ( b ) + static_cast <int> ( c ) ; // result == 9 // إذا تم استخدام التحويل الضمني ( كما هو الحال مع "result = a + b + c") ، فستكون النتيجة مساوية لـ 10

توجد عدة أنواع من التحويل الصريح.

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

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

لغة C# ولغة C++

في لغة C# ، يمكن إجراء تحويل النوع بطريقة آمنة أو غير آمنة (أي، تشبه لغة C)، وتسمى الأولى تحويل النوع المدقق . [ 9 ]

حيوان حيوان = قط جديد ();// إذا كان (الحيوان من نوع بولدوغ)، فإن stat.type(الحيوان) هو بولدوغ، وإلا استثناء Bulldog b = ( Bulldog ) animal ;// إذا كان (الحيوان من نوع بولدوغ)، فإن b = (بولدوغ)حيوان، وإلا فإن b = فارغ b = حيوان من نوع بولدوغ ؛// إزالة المرجع إلى Cat()، ووضع علامة عليه ليتم جمعه بواسطة جامع البيانات المهملة animal = null ;// b == null b = animal as Bulldog ;

في لغة C++، يمكن تحقيق تأثير مماثل باستخدام صيغة التحويل على نمط C++ .

حيوان * حيوان = قط جديد ();// يتم التجميع فقط إذا كان كل من Animal أو Bulldog مشتقًا من الآخر (أو من نفس النوع) Bulldog * b = static_cast < Bulldog *> ( animal );// إذا كان (الحيوان من نوع بولدوغ)، فإن b = (Bulldog*) animal، وإلا فإن b = nullptr b = dynamic_cast < Bulldog *> ( animal );// كما هو الحال أعلاه، ولكن سيتم طرح استثناء إذا كان من المفترض إرجاع مؤشر فارغ // هذا غير موجود في الكود الذي يتم فيه تجنب معالجة الاستثناءات Bulldog & br = static_cast < Bulldog &> ( * animal );// تحرير الذاكرة المخصصة للحيوان بعد الاستخدام delete animal ; animal = nullptr ;// b == nullptr b = dynamic_cast < Bulldog *> ( animal );

إيفل

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

الصدأ

لا توفر لغة Rust تحويلاً ضمنياً للأنواع (إجباراً) بين معظم الأنواع الأولية. ولكن، يمكن إجراء تحويل صريح للأنواع (تحويل نوعي) باستخدام الكلمة asالمفتاحية. [ 10 ]

let x : i32 = 1000 ; println! ( "1000 كـ u16 هو: {}" , x as u16 );

تأكيد النوع

يُعرف مفهومٌ ذو صلة في أنظمة الأنواع الثابتة باسم تأكيد النوع ، وهو يُوجّه المُصرّف للتعامل مع التعبير من نوعٍ مُحدد، متجاهلاً استنتاجه الخاص. قد يكون تأكيد النوع آمناً (يتم إجراء فحص أثناء التشغيل) أو غير آمن. لا يُحوّل تأكيد النوع القيمة من نوع بيانات إلى آخر.

تايب سكريبت

في TypeScript ، يتم إجراء تأكيد النوع باستخدام الكلمة asالمفتاحية: [ 11 ]

const myCanvas : HTMLCanvasElement = document . getElementById ( "main_canvas" ) as HTMLCanvasElement ;

في المثال أعلاه، document.getElementByIdتم تعريف الدالة على أنها تُرجع قيمة من النوع HTMLElement، ولكنك تعلم أنها تُرجع دائمًا قيمة من النوع HTMLCanvasElement، وهو نوع فرعي من HTMLElement، في هذه الحالة. إذا لم يكن الأمر كذلك، فلن يعمل الكود اللاحق الذي يعتمد على سلوك HTMLCanvasElementالدالة بشكل صحيح، لأنه في TypeScript لا يوجد فحص وقت التشغيل لتأكيدات النوع.

في لغة TypeScript، لا توجد طريقة عامة للتحقق من نوع قيمة معينة أثناء التشغيل، لعدم وجود دعم لأنواع البيانات في وقت التشغيل. مع ذلك، يُمكن كتابة دالة مُعرَّفة من قِبل المستخدم تُخبر المُصرِّف ما إذا كانت القيمة من نوع معين أم لا. تُسمى هذه الدالة " حارس النوع" ، ويتم تعريفها بنوع إرجاع `type` x is Type، حيث x`type` هو مُعامل أو this`type` بدلاً من `type` boolean.

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

يذهب

في لغة Go ، يمكن استخدام تأكيد النوع للوصول إلى قيمة نوع محددة من قيمة واجهة. وهو تأكيد آمن، حيث سيؤدي إلى حدوث خطأ فادح (في حالة قيمة إرجاع واحدة)، أو إرجاع قيمة صفرية (في حالة استخدام قيمتي إرجاع)، إذا لم تكن القيمة من ذلك النوع المحدد. [ 12 ]

t := i .( T )

تُخبر هذه التأكيدات النوعية النظام بأن هذا iالنوع هو T. إذا لم يكن كذلك، فإنه يُصاب بالذعر.

التحويل الضمني باستخدام الاتحادات غير الموسومة

تدعم العديد من لغات البرمجة أنواع الاتحاد التي يمكنها استيعاب قيمة من أنواع متعددة. وتُوفّر بعض اللغات ذات التحقق المتساهل من الأنواع، مثل C و PL/I ، وكذلك لغة باسكال الأصلية، أنواع الاتحاد غير المُصنّفة . ويمكن استخدامها لتفسير نمط البتات لنوع ما كقيمة من نوع آخر.

قضايا أمنية

في مجال القرصنة ، يُعدّ تحويل النوع إساءة استخدام لتحويل النوع لتغيير نوع بيانات متغير مؤقتًا عن نوعه الأصلي. [ 13 ] وهذا يتيح فرصًا للمخترقين، إذ بعد تحويل نوع متغير إلى نوع بيانات مختلف، سيتعامل المترجم مع هذا المتغير المُعدَّل على أنه نوع البيانات الجديد لتلك العملية المحددة. [ 14 ]

انظر أيضاً

مراجع

  1. 1 2 3 مهروترا، ديرج (2008). علوم الحاسوب لـ إس. تشاند . إس. تشاند. الصفحات 81-83 . ISBN  978-8121929844.
  2. لغات البرمجة - التصميم والتركيب . منشورات لاكشمي. 2013. ص 35. ISBN  978-9381159415.
  3. 1 2 رايلي، إدوين (2004). الموسوعة الموجزة لعلوم الحاسوب . جون وايلي وأولاده. ص 82، 110. ISBN  0470090952.
  4. فينتون، ستيف (2017). برو تايب سكريبت: تطوير تطبيقات جافا سكريبت واسعة النطاق . أبريس. ص. 23. ISBN  978-1484232491.
  5. "التعامل مع أنواع البيانات المختلفة" . دليل PHP . تم الاطلاع عليه بتاريخ 27 يناير 2019 .
  6. 1 2 أولسون، ميكائيل (2013). مرجع بناء الجملة السريع لـ C++ . Apress. ص 87 – 89. ISBN  978-1430262770.
  7. ^ كروس ، رودولف. بورجيلت، كريستيان؛ براون، كريستيان؛ مستغيم، سناز؛ ستينبريشر، ماتياس (16 سبتمبر 2016). الذكاء الحسابي: مقدمة منهجية . سبرينغر. ص. 269. ردمك  978-1447172963.
  8. "تحويلات الأنواع غير المُدققة" . مركز معلومات لغة آدا . تم الاطلاع عليه بتاريخ 11 مارس 2023 .
  9. ^ موسنبوك ، هانسبيتر (25 مارس 2002). ""C # المتقدم: قوالب النوع المحددة" (PDF) . معهد برمجيات النظم، جامعة يوهانس كيبلر لينز، Fachbereich Informatik. ص. 5 . تم الاسترجاع 4 أغسطس 2011 . في دروس لغة C#
  10. "الصب" . Rust by Example . تم الاسترجاع في 1 أبريل 2025 .
  11. "أنواع يومية" . دليل تايب سكريبت . تم الاطلاع عليه في 1 أبريل 2025 .
  12. "تأكيدات النوع" . جولة في لغة Go . تم ​​الاسترجاع في 1 أبريل 2025 .
  13. إريكسون، جون (2008). القرصنة: فن الاستغلال . دار نشر نو ستارش. ص 51. ISBN  978-1-59327-144-2."تحويل النوع هو ببساطة طريقة لتغيير نوع بيانات متغير مؤقتًا، بغض النظر عن كيفية تعريفه في الأصل. عندما يتم تحويل نوع متغير إلى نوع مختلف، يُطلب من المترجم التعامل مع هذا المتغير كما لو كان من النوع الجديد، ولكن فقط خلال هذه العملية. صيغة تحويل النوع هي كما يلي: (typecast_data_type) variable..."
  14. جوبال، أربيتا (2009). تكبير C. دار نشر PHI Learning Private Limited. ص 59. ISBN  978-81-203-3861-6.يتضح مما سبق أن استخدام تحويل الأنواع يهدف إلى جعل متغير من نوع معين يعمل كنوع آخر في عملية واحدة. لذا، باستخدام هذه الخاصية، يمكن إنشاء أحرف ASCII عن طريق تحويل عدد صحيح إلى نوعه الأصلي...