Явное приведение в C / C ++ - PullRequest
       15

Явное приведение в C / C ++

4 голосов
/ 17 октября 2019

После прочтения нескольких SO-сообщений на эту тему я все еще в замешательстве, в основном касательно целочисленных и логических переменных / выражений.

A. Целочисленные выражения

Предположим, я хочу использовать выражение по модулю в вычислениях с плавающей запятой, что, если оно есть, является наиболее правильным из следующих? Есть ли разница между C и C ++? или я должен просто доверить компилятору правильное преобразование?

double sign;
int num = rand() % 100;
//want to map odd num to -1.0 and even num to 1.0
//A
sign = -2 * (num % 2) + 1;
//B
sign = -2.0 * (num % 2) + 1;
//C
sign = -2.0 * (num % 2) + 1.0;
//D
sign = -2 * (num % 2) + 1.0;
//E
sign = -2 * (double)(num % 2) + 1;
//F
sign = -2.0 * (double)(num % 2) + 1;
//G
sign = -2.0 * (double)(num % 2) + 1.0;
//H
sign = -2 * (double)(num % 2) + 1.0;

B. Булевы выражения

Могу ли я использовать логическое выражение безопасно в качестве элемента в вычислениях с плавающей запятой / целыми числами без явного приведения? Есть ли разница между C и C ++?

double d_res = 1.0;
int i_res = 1;
int num = rand() % 10;
d_res = d_res + (num > 5);//or d_res = d_res + (double)(num > 5)?
i_res += (num > 5);//or i_res += (int)(num > 5)?

1 Ответ

6 голосов
/ 17 октября 2019

A. Инициализация

double sign = -2 * (num % 2) + 1;

совершенно четко определена. Это то, что я бы использовал;Я не думаю, что есть необходимость усложнять вещи дополнительными приведениями или чем-то еще.

C и C ++ хорошо определены и удобны в неявных преобразованиях между целочисленными типами и типами с плавающей точкой. Явные преобразования обычно не нужны. По моему опыту, есть только три вещи, о которых нужно беспокоиться:

  • Код вроде double ratio = 1 / 3 не делает то, что вы хотите;вам нужно заставить один из операндов / быть плавающей точкой. (Это не имеет никакого отношения к вашему вопросу, но сделать ошибку очень легко.)
  • Переполнение, если один тип или другой не может представлять значение. (Также не проблема для вашего примера.)
  • Чрезмерно усердные компиляторы. Многие компиляторы предупредительно предупреждают вас, что вы можете потерять точность при преобразовании из double в float или из типа с плавающей точкой в ​​целое число. Таким образом, вам может потребоваться явное приведение, чтобы заставить замолчать эти предупреждения.

B. Запрос числового значения логического значения является совершенно четким (гарантированно даст вам хороший результат,чистый, 1 или 0), так что ваш второй фрагмент тоже должен быть в порядке. (Я знаю, что это верно для C, и согласно комментарию ниже, это верно и для C ++.)

...