Почему оператор модуля (%) работает для char, но не для плавающих типов?

#include <stdio.h>

int main()
{
  char c;
  c=10;
  if(c%2==0)
    printf("Yes");
  return 0;
}

Приведенный выше код печатает «Да». Может кто-нибудь сказать, почему оператор модуля работает для char и int, но не для double и т. д.?


person user1799762    schedule 16.08.2014    source источник
comment
Потому что char — целочисленный тип. Для типов с плавающей запятой используйте fmod().   -  person Oliver Charlesworth    schedule 16.08.2014
comment
Потому что char — это 8-битное целое число. double не является целым числом.   -  person Hot Licks    schedule 16.08.2014
comment
@HotLicks char – это минимум 8-битное целое число. Однако, поскольку можно легко определить операцию по модулю над нецелыми числами, это на самом деле не отвечает на вопрос. (На вопрос в стиле «почему» единственный ответ, вероятно, состоит в том, что именно так его определяет стандарт C.)   -  person The Paramagnetic Croissant    schedule 16.08.2014
comment
@ThePara MagneticCroissant: Если вопрос в том, почему это так?, то ответ может быть только потому, что так говорит языковой стандарт. Конечно, стоит отметить, что характеристики арифметики с плавающей запятой означают, что оператор по модулю не всегда будет делать то, на что можно было бы надеяться.   -  person Oliver Charlesworth    schedule 16.08.2014
comment
@OliCharlesworth Точно. Позвольте мне добавить это тоже. (относительно характеристик FP: как и сложение, умножение или практически любая другая операция FP, но у них все еще есть свои собственные операторы. Было бы совершенно разумно, чтобы % работал и с типами с плавающей запятой.)   -  person The Paramagnetic Croissant    schedule 16.08.2014
comment
@ThePara MagneticCroissant: Не обязательно. Оператор % для целых чисел определяется в терминах /; это равенство не обязательно выполняется в арифметике с плавающей запятой.   -  person Oliver Charlesworth    schedule 16.08.2014
comment
@OliCharlesworth, а как насчет других операторов? * и / определены как для целочисленных типов, так и для типов с плавающей запятой, хотя они также не делают одно и то же (такие тождества, как a * b / b == a, сохраняются для целых чисел, но не для типов FP). Так почему же нельзя было определить и %? Зная о неточном характере арифметики с плавающей запятой, можно было бы ожидать, что a / b * b + a % b != a. (Кроме того, поскольку целые числа и числа с плавающей запятой являются разными типами, нет проблем с определением определенной операции для них немного по-разному.)   -  person The Paramagnetic Croissant    schedule 16.08.2014
comment
@theparamagneticcroissant: да, это справедливо. Тем не менее, стандарт такой, какой он есть ;)   -  person Oliver Charlesworth    schedule 16.08.2014
comment
Я думаю, что на большинство этих комментариев следует ответить, а не только на комментарии ›o‹   -  person ikh    schedule 16.08.2014
comment
@OliCharlesworth Да, определенно :) И я не против, просто пытаюсь оправдать вопрос ОП: P   -  person The Paramagnetic Croissant    schedule 16.08.2014
comment
Несмотря на то, что % похоже, его лучше называть оператором остатка, а не модулем; то, что спецификация C называет это. Бен хорошо рассказал о различиях.   -  person chux - Reinstate Monica    schedule 16.08.2014


Ответы (1)


Вы уже получили комментарии, объясняющие, почему % определено для char: оно определено для всех целочисленных типов, а в C char является целочисленным типом. Некоторые другие языки определяют отдельный тип char, который не поддерживает арифметические операции, но C не входит в их число.

Но чтобы ответить, почему он не определен для типов с плавающей запятой: history. Нет технической причины, по которой было бы невозможно определить оператор % для типов с плавающей запятой. Вот что говорит обоснование C99:

6.5.5 Мультипликативные операторы

[...]

Комитет C89 отклонил расширение оператора % для работы с плавающими типами, поскольку такое использование дублировало бы возможности, предоставляемые fmod (см. §7.12.10.1).

И как позже обнаружил мафсо:

7.12.10.1 Функции fmod

[...]

Комитет C89 рассмотрел предложение использовать оператор остатка % для этой функции; но он был отклонен, потому что операторы в целом соответствуют аппаратным средствам, а fmod не поддерживается аппаратно на большинстве машин.

Они кажутся несколько противоречивыми. Оператор % не был расширен, потому что fmod уже удовлетворил эту потребность, но fmod был выбран для удовлетворения этой потребности, потому что комитет не хотел расширять оператор %? Оба они не могут быть истинными одновременно.

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

person Community    schedule 16.08.2014
comment
Я бы предложил добавить (там же 7.12.10.1 стр.5) «Комитет C89 рассмотрел предложение использовать оператор остатка % для этой функции; но он был отклонен, потому что операторы в целом соответствуют аппаратным средствам, а fmod не поддерживается аппаратно на большинстве машин». - person mafso; 16.08.2014
comment
@mafso Спасибо, но это странно. Кажется, это противоречит тому, что я нашел. - person ; 16.08.2014
comment
Это просто еще одна причина, указанная в том же документе, хотя немного странно иметь А, потому что Х в одном месте, а А в другом, потому что Y, а не просто А, потому что X и Y. Но я не вижу противоречия. - person mafso; 16.08.2014
comment
@mafso Я вижу это скорее как A, потому что B, и B, потому что A, и подозреваю, что оба были правильными в какой-то момент, но никогда оба одновременно. - person ; 16.08.2014
comment
Я вижу вашу точку зрения. Я прочитал первое, так как нет необходимости в операторе, потому что это может сделать функция (а второе, что было бы против духа C), а не потому, что у нас уже есть эта функция, поэтому нет необходимости в операторе (и если мы обработали предложения в другом порядке, мы могли бы опустить fmod и вместо этого определить оператор). - person mafso; 16.08.2014