Двойное литье значения в C для 64-битного умножения [дубликат]

Почему вы не должны и , когда вы должны использовать регулярные выражения?

Во-первых, обычное неправильное выражение: регулярные выражения не предназначены для «синтаксического анализа» ] HTML. Regexes может, однако, «извлечь» данные. Извлечение - это то, для чего они созданы. Основным недостатком выработки HTML-выражения в правильных инструментариях SGML или базовых синтаксических анализаторов XML является их синтаксическое усилие и различная надежность.

Считайте, что создание несколько надежного HTML-выражения regex:

]+id="(\d+)".+?    ]+href="(http://[^">]+)"[^>]*>([^<>]+).+?

является менее читаемым, чем простой эквивалент phpQuery или QueryPath:

$div->find(".stationcool a")->attr("title");

Существуют, однако, конкретные варианты использования, в которых они могут помочь.

  • Многие интерфейсы обхода DOM не показать комментарии HTML (.+?)/ и обработать остаток, используя более простые интерфейсы парсера HTML.

    Примечание. У меня на самом деле есть это приложение , где я использую разбор XML и регулярные выражения альтернативно. На прошлой неделе разразился синтаксический анализ PyQuery, и регулярное выражение все еще работало. Да, странно, и я не могу объяснить это сам. Но так получилось. Поэтому, пожалуйста, не голосуйте за реальные соображения, потому что это не соответствует регулярному выражению = evil mem. Но давайте также не будем проголосовать за это слишком много. Это всего лишь побочный сигнал для этой темы.

29
задан hippietrail 20 January 2016 в 10:33
поделиться

6 ответов

Согласно стандарту ISO C, когда вы преобразовываете целое число в подписанный тип, а значение выходит за пределы целевого типа, результат определяется реализацией. (Или сигнал, определяемый реализацией, может быть поднят, но я не знаю каких-либо компиляторов, которые это делают.)

На практике наиболее распространенным поведением является то, что старшие разряды отбрасываются. Таким образом, предполагая, что int - 32 бита, а short - 16 бит, преобразование значения 0x1248642, вероятно, даст бит-шаблон, который выглядит как 0x8642. Предполагая, что для подписанных типов (которые используются почти для всех систем) представление с двумя дополнениями, старший бит является знаковым битом, поэтому числовое значение результата будет -31166.

int y   =   sx;

Это также подразумевает неявное преобразование, от short до int. Поскольку диапазон int гарантированно покрывает по крайней мере весь диапазон short, значение не изменяется. (Так как в вашем примере значение sx оказывается отрицательным, это изменение представления скорее всего будет связано с расширением знака , распространяющим бит знака 1 на все 16 старших разрядов результата.)

Как я указал, ни одна из этих деталей не требуется по языковому стандарту. Если вы действительно хотите усечь значения до более узкого типа, лучше всего использовать неподписанные типы (которые имеют заданное по языку поведение wraparound) и, возможно, явные операции маскировки, например:

unsigned int x = 0x1248642;
unsigned short sx = x & 0xFFFF;

Если у вас есть 32-битное количество, которое вы хотите вставить в 16-битную переменную, первое, что вам нужно сделать, это решить, как вы хотите, чтобы ваш код работал, если значение не подходит. Как только вы это решите, вы можете понять, как писать код C, который делает то, что вы хотите. Иногда усечение происходит именно так, как вы хотите, и в этом случае ваша задача будет легкой, особенно если вы используете неподписанные типы. Иногда значение вне диапазона является ошибкой, и в этом случае вам нужно проверить его и решить, как обрабатывать ошибку. Иногда вам может потребоваться насыщение, а не усечение, поэтому вам нужно написать код для этого.

Знание того, как работают преобразования на C, но если вы запустите с этим вопросом, вы просто можете приблизиться к своей проблеме с неправильного направления.

34
ответ дан Keith Thompson 26 August 2018 в 09:06
поделиться

32-битное значение усечено до 16 бит таким же способом, если бы бабановый хлеб длиной 32 см был бы вырезан, если вы застреваете его в кастрюлю длиной 16 см. Половина из них подойдет и останется банановым хлебом, а остальное будет «ушло».

9
ответ дан chqrlie 26 August 2018 в 09:06
поделиться

Возможно, пусть код говорит сам за себя:

#include <stdio.h>

#define BYTETOBINARYPATTERN "%d%d%d%d%d%d%d%d"
#define BYTETOBINARY(byte)  \
   ((byte) & 0x80 ? 1 : 0), \
   ((byte) & 0x40 ? 1 : 0), \
   ((byte) & 0x20 ? 1 : 0), \
   ((byte) & 0x10 ? 1 : 0), \
   ((byte) & 0x08 ? 1 : 0), \
   ((byte) & 0x04 ? 1 : 0), \
   ((byte) & 0x02 ? 1 : 0), \
   ((byte) & 0x01 ? 1 : 0) 

int main()
{
    int x    =   0x1248642;
    short sx = (short) x;
    int y    =   sx;

    printf("%d\n", x);
    printf("%hu\n", sx);
    printf("%d\n", y);

    printf("x: "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN"\n",
        BYTETOBINARY(x>>24), BYTETOBINARY(x>>16), BYTETOBINARY(x>>8), BYTETOBINARY(x));

    printf("sx: "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN"\n",
        BYTETOBINARY(y>>8), BYTETOBINARY(y));

    printf("y: "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN"\n",
        BYTETOBINARY(y>>24), BYTETOBINARY(y>>16), BYTETOBINARY(y>>8), BYTETOBINARY(y));

    return 0;
}

Выход:

19170882
34370
-31166

x: 00000001 00100100 10000110 01000010
sx: 10000110 01000010
y: 11111111 11111111 10000110 01000010

Как вы можете видеть, int -> short дает нижние 16 бит, как и ожидалось.

В режиме short - int значение short с установленными 16 битами. Однако я подозреваю, что это специфическое и неопределенное поведение для реализации. Вы, по сути, интерпретируете 16 бит памяти как целое число, которое читает 16 дополнительных битов любого мусора, если они есть (или 1, если компилятор хорош и хочет помочь вам быстрее найти ошибки).

I думаю, что должно быть безопасно сделать следующее:

int y = 0x0000FFFF & sx;

Очевидно, что вы не вернете потерянные биты, но это гарантирует, что высокие биты будут правильно обнулены .

Если кто-то может проверить короткое -> int высокое битовое поведение с авторитетной ссылкой, это будет оценено.

Примечание: двоичный макрос, адаптированный из этого ответа .

3
ответ дан Community 26 August 2018 в 09:06
поделиться

Усечение происходит в регистры процессора. Они имеют разные размеры: 8/16/32/64 бит. Теперь вы можете представить себе такой регистр, как:

<--rax----------------------------------------------------------------> (64-bit)
                                    <--eax----------------------------> (32-bit)
                                                      <--ax-----------> (16-bit)
                                                      <--ah--> <--al--> (8-bit high & low)
01100011 01100001 01110010 01110010 01111001 00100000 01101111 01101110

x сначала задано 32-битное значение 0x1248642. В памяти * это будет выглядеть так:

-----------------------------
|  01  |  24  |  86  |  42  |
-----------------------------
 31..24 23..16 15..8  7..0       

Теперь компилятор загружает x в регистр. Из него он может просто загрузить наименее значимые 16 бит (а именно ax) и сохранить их в sx.


* Для простоты энтузиазм не учитывается

5
ответ дан Dan Bechard 26 August 2018 в 09:06
поделиться
Значение

sx будет таким же, как 2 младших значащих байта x, в этом случае оно будет 0x8642, которое (если оно интерпретируется как 16-разрядное целое число со знаком) дает -31166 в десятичной форме.

2
ответ дан nsilent22 26 August 2018 в 09:06
поделиться

Просто высокие 16 бит обрезаются от целого. Поэтому ваш короткий станет 0x8642, который на самом деле является отрицательным числом -31166.

4
ответ дан Zbynek Vyskovsky - kvr000 26 August 2018 в 09:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: