Приведение символа к короткому без знака: что происходит за кулисами? - PullRequest
1 голос
/ 31 декабря 2008

Учитывая это поле:

char lookup_ext[8192] = {0}; // Gets filled later

И это утверждение:

unsigned short *slt = (unsigned short*) lookup_ext;

Что происходит за кадром?

lookup_ext [1669] возвращает 67 = 0100 0011 (C), lookup_ext [1670] возвращает 78 = 0100 1110 (N), а lookup_ext [1671] возвращает 68 = 0100 0100 (D); пока slt [1670] возвращает 18273 = 0100 0111 0110 0001.

Я пытаюсь перенести это на C #, поэтому помимо простого выхода из этого, мне также интересно, что на самом деле здесь происходит. Прошло много времени с тех пор, как я регулярно использовал C ++.

Спасибо!

Ответы [ 4 ]

6 голосов
/ 31 декабря 2008

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

Обратите внимание, что sizeof(unsigned short) вряд ли будет единица, поэтому slt[1670] не обязательно будет соответствовать lookup_ext[1670]. Более вероятно - если, скажем, sizeof(unsigned short) равно двум - соответствовать lookup_ext[3340] и lookup_ext[3341].

Знаете ли вы, почему оригинальный код использует этот псевдоним? Если в этом нет необходимости, возможно, стоит попробовать очистить код C ++ и убедиться, что поведение не изменилось перед его портированием.

2 голосов
/ 31 декабря 2008

Если я правильно понимаю, преобразование типа будет преобразовывать массив символов размера 8192 в короткий массив типа int, равный половине того, который равен 4096.

Так что я не понимаю, что вы сравниваете в своем вопросе. slt [1670] должен соответствовать lookup_ext [1670 * 2] и lookup_ext [1670 * 2 + 1].

1 голос
/ 31 декабря 2008

Ну, это утверждение

char lookup_ext[8192] = {0}; // Gets filled later

Создает массив локально или нелокально, в зависимости от того, где находится определение. Инициализируя его, агрегатный инициализатор инициализирует все его элементы до нуля (первый явно, остальные неявно). Поэтому мне интересно, почему ваша программа выводит ненулевые значения. Если заполнение не произойдет до чтения, это имеет смысл.

unsigned short *slt = (unsigned short*) lookup_ext;

Это будет интерпретировать байты, составляющие массив, как беззнаковые короткие объекты, когда вы читаете из цели этого указателя. Строго говоря, вышеприведенное поведение не определено, поскольку вы не можете быть уверены, что массив подходит для выравнивания, и вы читали бы из указателя, который не указывает на тип исходного заостренного типа (unsigned char <-> unsigned short). В C ++ единственный переносимый способ считывания значения из некоторого другого модуля (простые старые данные. Это все структуры и простые типы, которые возможны и в C (например, короткие), в широком смысле) - использование таких библиотечных функций, как memcpy или memmove.

Таким образом, если вы прочитаете *slt выше, вы интерпретируете первые sizeof(*slt) байты массива и пытаетесь прочитать его как беззнаковое короткое (это называется type pun).

0 голосов
/ 31 декабря 2008

Когда вы делаете "unsigned short slt = (unsigned short ) lookup_ext;", no. байтов, эквивалентных размеру (unsigned short), выбираются из местоположения, заданного lookup_ext, и сохраняются в месте, указанном slt. Поскольку unsigned short будет 2 байта, первые два байта из lookup_ext будут храниться в месте, указанном slt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...