لماذا "(int) (char) (بايت) -2" ينتج 65534 في Java؟



2 Answers

هناك شيئين مهمين يجب ملاحظتهما هنا ،

  1. char غير موقع ، ولا يمكن أن يكون سالبة
  2. صب البايت ل char أول ينطوي على يلقي خفية إلى كثافة العمليات وفقا لمتطلبات لغة جافا .

وبالتالي ، فإن الصب -2 إلى int يمنحنا 1111111111111111111111111111111110. لاحظ كيف أن القيمة التكميلية للاثنين تم تمديدها بعلامة واحدة ؛ الذي يحدث فقط للقيم السلبية. عندما نضيقها إلى char ، يتم اقتطاع int

1111111111111110

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

java casting

لقد واجهت هذا السؤال في اختبار تقني لوظيفة. إعطاء مثال التعليمة البرمجية التالية:

public class Manager {
    public static void main (String args[]) {
        System.out.println((int) (char) (byte) -2);
    }
}

يعطي الإخراج كـ 65534.

يظهر هذا السلوك للقيم السالبة فقط؛ 0 والأرقام الموجبة تعطي نفس القيمة ، أي القيمة المدخلة في SOP. البايت يلقي هنا غير مهم. لقد حاولت بدونها.

إذن ، سؤالي هو: ما الذي يحدث هنا بالضبط؟




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

Instance | #          int            |     char    | #   byte    |    result   |
Source   | 11 11 11 11 | 11 11 11 11 | 11 11 11 11 | 11 11 11 10 | -2          |
byte     |(11 11 11 11)|(11 11 11 11)|(11 11 11 11)| 11 11 11 10 | -2          |
int      | 11 11 11 11 | 11 11 11 11 | 11 11 11 11 | 11 11 11 10 | -2          |
char     |(00 00 00 00)|(00 00 00 00)| 11 11 11 11 | 11 11 11 10 | 65534       |
int      | 00 00 00 00 | 00 00 00 00 | 11 11 11 11 | 11 11 11 10 | 65534       |
  1. أنت ببساطة تأخذ قيمة موقعة 32 بت.
  2. أنت ثم تحويله إلى قيمة موقعة 8bit.
  3. عند محاولة تحويله إلى قيمة غير موقعة 16 بت ، يتسلل المحول البرمجي في تحويل سريع إلى قيمة موقعة 32 بت ،
  4. ثم تحويله إلى 16bit دون الحفاظ على علامة.
  5. عندما يحدث التحويل النهائي إلى 32 بت ، لا يوجد أي إشارة ، لذلك تضيف القيمة صفر بت للحفاظ على القيمة.

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

(يرجى ملاحظة ، لقد استخدمت علامة # للدلالة على بت الموقّع ، وكما هو موضح ، لا يوجد بتات موقعة لـ char ، حيث أنها قيمة غير موقعة).

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

يتم دائمًا توسيع القيم الموقعة مع قيمة بت الموقعة. غير الموقعة دائما تتسع مع قليلا قبالة.

* لذا ، فإن الخدعة (أو gotchas) لهذا ، هي أن التوسع إلى int من بايت ، يحافظ على القيمة الموقعة عند الاتساع. ثم يتم تضييقها في اللحظة التي تلمس فيها الحرف. هذا ثم إيقاف تشغيل بت الموقع.

إذا لم يحدث التحويل إلى int ، فإن القيمة ستكون 254. لكن ، إنها كذلك ، لذا فهي ليست كذلك.




Related


Tags

java   casting