سؤال

إذا كان لدي مجموعة من ints قصيرة غير موقعة.

هل سيقوم تحويل الصفيف [K+1] بترك 8 بتات ، وضع 8 بت في النصف السفلي من الصفيف [K+1]؟

أم أنها ببساطة تنزل لأنهم خرجوا خارج المساحة المخصصة للعنصر؟

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

المحلول

انهم ينزلون. لا يمكنك التأثير على البتات الأخرى بهذه الطريقة. جربها:

#include <stdio.h>

void print_a (short * a)
{
    int i;
    for (i = 0; i < 3; i++)
        printf ("%d:%X\n", i, a[i]);
}

int main ()
{
    short a[3] = {1, -1, 3};
    print_a (a);
    a[1] <<= 8;
    print_a (a);
    return 0;
}

الإخراج هو

0:1
1:FFFFFFFF
2:3
0:1
1:FFFFFF00
2:3

نصائح أخرى

إنهم ينزلون نوع البيانات تمامًا ، ولا ينقلون إلى عنصر الصفيف التالي.

إذا كنت تريد هذا النوع من السلوك ، فيجب عليك ترميزه بنفسك بشيء مثل (اليسار يغير الصفيف بأكمله بأربعة بت):

#include <stdio.h>
int main(void) {
    int i;
    unsigned short int a[4] = {0xdead,0x1234,0x5678,0xbeef};

    // Output "before" variables.

    for (i = 0; i < sizeof(a)/sizeof(*a); i++)
        printf ("before %d: 0x%04x\n", i, a[i]);
    printf ("\n");

    // This left-shifts the array by left-shifting the current
    // element and bringing in the top bit of the next element.
    // It is in a loop for all but hte last element.
    // Then it just left-shifts the last element (no more data
    // to shift into that one).

    for (i = 0; i < sizeof(a)/sizeof(*a)-1; i++)
        a[i] = (a[i] << 8) | (a[i+1] >> 8);
    a[i] = (a[i] << 8);

    // Print the "after" variables.

    for (i = 0; i < sizeof(a)/sizeof(*a); i++)
        printf ("after  %d: 0x%04x\n", i, a[i]);

    return 0;
}

هذا المخرجات:

before 0: 0xdead
before 1: 0x1234
before 2: 0x5678
before 3: 0xbeef

after  0: 0xad12
after  1: 0x3456
after  2: 0x78be
after  3: 0xef00

طريقة التفكير في ذلك هي أنه في C (ولغات معظم اللغات) التنفيذ array[k] << 8 يتضمن تحميل صفيف [K] في السجل ، وتحويل السجل ، ثم تخزين السجل مرة أخرى في Array [K]. وهكذا ستبقى الصفيف [K+1] دون أن تمس.

كمثال، foo.c:

unsigned short array[5];

void main() {
  array[3] <<= 8;
}

سيقوم بإنشاء التعليمات التالية:

movzwl  array+6(%rip), %eax
sall    $8, %eax
movw    %ax, array+6(%rip)

هذا يحمل الصفيف [3] إلى ٪ eax ، ويعدلها ، ويخزنها مرة أخرى.

إن تحويل INT غير موقّع الذي تركته 8 بتات سوف يملأ 8 بتات أقل من الأصفار. سيتم التخلص من أعلى 8 بت ، لا يهم أنها في صفيف.

بالمناسبة ، ما إذا كانت 8 بت هي نصف INT غير موقعة يعتمد على نظامك ، ولكن على أنظمة 32 بت ، فإن 8 بتات عادة ما تكون ربع int غير موقعة.

unsigned int x = 0x12345678;
// x is 0x12345678

x <<= 8;
// x is 0x34567800

كن على دراية بأن تعريف C لنوع بيانات Int لا يحدد عدد البتات التي تحتوي عليها ويعتمد على النظام. كان المقصود في الأصل أن يكون حجم الكلمة "الطبيعي" للمعالج ، ولكن هذا ليس كذلك دائمًا ويمكن أن تجد INT يحتوي على 16 أو 32 أو 64 أو حتى بعض الأرقام الفردية مثل 24 بت.

الشيء الوحيد الذي تضمنه هو int غير موقعة يمكن أن يحتفظ بجميع القيم بين 0 و uint_max شاملة ، حيث يجب أن يكون UINT_MAX 65535 على الأقل - لذلك يجب أن تحتوي أنواع int على 16 بت على الأقل لعقد النطاق المطلوب من القيم.

لذا فإن تحويل مجموعة من عدد صحيح بمقدار 8 بتات سيتغير كل من INT بشكل فردي ، ولكن كن على دراية بأن هذا التحول لن يكون بالضرورة "نصف المصفوفة"

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