Как хранился массив char? - PullRequest
0 голосов
/ 05 июля 2018

Вот что-то странное, что я нашел:

Когда у меня есть char * s из трех элементов, и я присвоил ему значение «21»,

  1. Напечатанное короткое int значение s выглядит как 12594, что соответствует 0010001 0010010 в двоичном формате, и 49 50 для отдельного символа. Но согласно диаграмме ASCII значение «2» равно 50, а «1» - 49.

  2. когда я сдвигаю символ вправо, *(short*)s >>= 8, результат согласуется с (1.), который равен '1' или 49. Но после того, как я назначил символ *s = '1', напечатанная строка s также выглядит как «1», который, как я ранее думал, станет «11».

Я немного озадачен тем, как биты хранятся в символе, надеюсь, кто-нибудь сможет это объяснить.

Ниже приведен код, который я использую:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
  printf("%lu,%lu\n",sizeof(char), sizeof(short));
  char* s = malloc(sizeof(char)*3);
  *s = '2', *(s+1) = '1', *(s+2) = '\0';
  printf("%s\n",s);
  printf("%d\n",*(short int*)s);
  *(short*)s >>= 8;
  printf("%s\n",s);
  printf("%d\n",*(short int*)s);
  *s = '1';
  printf("%s\n",s);
  return 0;
}

И вывод:

1,2
21
12594
1
49
1

Эта программа скомпилирована на macOS с gcc.

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

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

Тогда ответ на ваш вопрос называется endianess. В представлении с прямым порядком байтов самый старший байт имеет самый низкий адрес (258 или 0x102 будет представлен как 2 байта 0x01, 0x02 в этом порядке), тогда как в представлении с меньшим порядком байтов младший значащий байт имеет самый низкий адрес (0x102 представлен как 0x02, 0x01 в этом порядке).

Ваша система немного порядковая.

0 голосов
/ 05 июля 2018

Вам необходимо некоторое понимание понятия «порядковый номер» здесь, чтобы значения могли быть представлены как «младший порядок» и «большой порядок».

Я собираюсь пропустить обсуждение того, насколько это законно, о вовлеченном неопределенном поведении.
(Вот, однако, соответствующая ссылка, предоставленная Lundin, кредиты:
Что такое строгое правило наложения имен? )

Но давайте посмотрим на пару байтов в памяти, из которых младший адрес содержит 50, а старший адрес содержит 49:

50 49

Вы вводите их именно таким образом, явно устанавливая младший и старший байты (через тип char).

Затем вы читаете их, заставляя компилятор считать его short, который является типом размером в два байта в вашей системе.

Компиляторы и аппаратные средства могут создаваться с разными «мнениями» о том, что является хорошим представлением двухбайтовых значений в двух последовательных байтах. Это называется "endianess".

Два компилятора, оба из которых полностью соответствуют стандартам, могут действовать следующим образом:

Возвращаемое short 1024 *

  • взять значение с более низкого адреса, умножить его на 256, добавить значение с более высокого адреса
  • взять значение с старшего адреса, умножить его на 256, добавить значение с младшего адреса

На самом деле они этого не делают, это гораздо более эффективный механизм, реализованный в аппаратном обеспечении, но дело в том, что даже реализация в аппаратной простоте делает то или иное.

...