При приведении массива int к короткому *, почему присвоение значения элементу перезаписывает все целое число? - PullRequest
1 голос
/ 02 января 2012

Я смотрю видеофильм Джерри Кейна *1001* Programming Paradigms , где демонстрируется эффект назначения элемента после приведения между массивом int и коротким массивом. По сути, аргумент заключается в том, что если вы назначите элемент массива int arr[3] = 128, затем временно преобразуете массив int в короткий * и присвойте arr[6] = 2, тогда arr [3] должен стать 128 + 512 = 640, потому что 2 будет быть интерпретированным как находящийся в 2 ^ 9-й позиции. Код для демонстрации:

#include <stdio.h>

int main() {
  printf("sizeof(int) is %lu\n", sizeof(int));
  printf("sizeof(short) is %lu\n", sizeof(short));
  int arr[5];
  arr[3] = 128;
  ((short*)arr)[6] = 2;
  printf("arr[3] is equal to %d\n", arr[3]); //expect 640, get 2 instead
  return 0;
}

Когда я запускаю этот код, я получаю следующий вывод:

sizeof(int) is 4
sizeof(short) is 2
arr[3] is equal to 2

Я ожидаю, что arr [3] будет равен 640, но вместо этого он просто равен 2. Я по общему признанию C noob - кто-нибудь может объяснить?

1 Ответ

5 голосов
/ 02 января 2012

Big-endian против little-endian, я думаю.

Код по своей сути зависит от платформы (официально, почти наверняка неопределенное поведение).Я не уверен, что вас учат этому, но, думаю, это проблема другого времени.

2 присваивается двум из четырех байтов arr[3].Если вместо этого назначить ((short *)arr)[7], вы можете увидеть ожидаемый результат.

На какой машине вы тестируете (какой тип процессора)?


Если подумать - хотя и частичнопроблема, возможно, имеет порядок с прямым порядком байтов по сравнению с прямым порядком байтов, другая проблема - short против char.Вот еще несколько кодов, которые показывают различные пути решения:

#include <stdio.h>

int main(void)
{
    printf("sizeof(int) is %lu\n", sizeof(int));
    printf("sizeof(short) is %lu\n", sizeof(short));
    int arr[5];

    arr[3] = 128;
    ((short*)arr)[6] = 2;
    printf("arr[3] is equal to %8d (0x%08X)\n", arr[3], arr[3]);

    arr[3] = 128;
    ((short*)arr)[7] = 2;
    printf("arr[3] is equal to %8d (0x%08X)\n", arr[3], arr[3]);

    for (int i = 12; i < 16; i++)
    {
        arr[3] = 128;
        ((char *)arr)[i] = 2;
        printf("arr[3] is equal to %8d (0x%08X) i = %d\n", arr[3], arr[3], i);
    }

    return 0;
}

Вывод этого пересмотренного кода:

sizeof(int) is 4
sizeof(short) is 2
arr[3] is equal to        2 (0x00000002)
arr[3] is equal to   131200 (0x00020080)
arr[3] is equal to        2 (0x00000002) i = 12
arr[3] is equal to      640 (0x00000280) i = 13
arr[3] is equal to   131200 (0x00020080) i = 14
arr[3] is equal to 33554560 (0x02000080) i = 15

Тестирование на MacOS X 10.7.2 с GCC 4.2.1XCode 4.2 (LLVM).

...