2015-11-19 5 views
3

Привет, я знаю в Cmodulo отрицательного дивиденда приводит к отрицательному модулю, но я обнаружил, что по модулю отрицательного дивиденда с использованием длинного беззнакового делитель или длинный длинный неподписанный делитель приводит к положительному модулю!C Сбой работы модуля с отрицательным дивидендом и делителем длинный без знака

Вот пример:

#include <stdio.h> 

int main(int argc, char** argv) 
{ 
    long long int a = -2205348223670655684LL; 
    printf("%lld %lld %lld %lld %lld %lld\n", a % 20, a % 20L, a % 20LL, a % 20U, a % 20LU, a % 20LLU); 
    return 0; 
} 

и выход:

$> ./a.out 
-4 -4 -4 -4 12 12 

Может кто-нибудь объяснить, почему? Я попытался его с GCC 4.8 и 5.1

+3

«По модулю отрицательного дивиденда результат отрицательный по модулю» неправильный. Это определяется реализацией. –

+0

@ н.м. ... в более ранних стандартах C. – user694733

+0

Также я знаю, что в pre C11 стандартно этот модуль с отрицательным знаком был специфичным для реализации, но в любом случае меня интересует также обоснование реализации, и я не могу найти в текущем стандарте все, что объясняет это поведение либо – tsilvestre

ответ

4

C99 раздел 6.5.5/6 требует, чтобы при а/Ь представима:

(а/б) * б + а% б должен равняться

А из 6.5.5/3

обычные арифметические преобразования выполняются над операндами.

Подробнее об арифметическом преобразовании см. Раздел 6.3.1.8.

Теперь, похоже, от реализации sizeof(long) = sizeof(long long) = 64 bits

В течение первых 4-х случаях, знаком или без знака делитель может быть изменен на тип числителе (т.е. long long int), но в последние 2 случаях дивиденды должны быть изменены (литая или переосмыслил as) к неподписанному типу, поскольку делитель имеет одинаковую ширину и не имеет значения, что приводит к результату.

В некоторых системах, где sizeof(long) < sizoef(long long), второй последний результат должен быть разным.

3

Существует не такая вещь, как (встроенная) арифметическая операция, выполняемая с одним подписанным и одним неподписанным операндом; оба операнда двоичной операции получают один и тот же тип.

В ваших последних двух примерах этот тип unsigned long long; поэтому a преобразуется в значение без знака, а остаток вычисляется с использованием этого.

 Смежные вопросы

  • Нет связанных вопросов^_^