Разделить без потери остатка

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

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

val=num / 10;
mod=num % 10;

Ответ 1

Вы всегда можете использовать функцию div.

Ответ 2

Я бы не беспокоился о подсчете команд, потому что набор команд x86 предоставит команду idivl, которая вычисляет дивиденды и остаток в одной инструкции. Любой достойный компилятор будет использовать эту инструкцию. Представление здесь http://programminggroundup.blogspot.com/2007/01/appendix-b-common-x86-instructions.html описывает инструкцию следующим образом:

Выполняет беззнаковое деление. Разделяет содержимое двойного слова содержащихся в объединенных регистрах% edx:% eax по значению в регистр или ячейку памяти. Регистр% eax содержит результирующий фактор, а регистр% edx содержит результирующий остаток. Если частное слишком велико, чтобы соответствовать в% eax, оно вызывает прерывания типа 0.

Например, компиляция этой примерной программы:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
  int x = 39;
  int divisor = 1;
  int div = 0;
  int rem = 0;

  printf("Enter the divisor: ");
  scanf("%d", &divisor);
  div = x/divisor;
  rem = x%divisor;

  printf("div = %d, rem = %d\n", div, rem);
}

С gcc -S -O2 (-S сохраняет созданный файл tempory, который показывает листинг asm), показывает, что деление и мода в следующих строках

div = x/divisor;
rem = x%divisor;

эффективно сводится к следующей инструкции:

idivl   28(%esp)

Как вы можете видеть, одна инструкция для выполнения вычисления деления и мод. Инструкция idivl сохраняется, даже если вычисление мод в программе C будет удалено. После idivl появляются вызовы mov:

movl    $.LC2, (%esp)
movl    %edx, 8(%esp)
movl    %eax, 4(%esp)
call    printf

Эти вызовы копируют фактор и остаток в стек для вызова printf.

Update

Интересно, что функция div не делает ничего особенного, кроме обертывания операторов/и% в вызове функции. Поэтому с точки зрения производительности он не улучшит производительность, заменив строки

 val=num / 10;       
 mod=num % 10;

с одним вызовом div.

Ответ 3

Там div():

div_t result = div(num, 10);
// quotient is result.quot
// remainder is result.rem

Ответ 4

Не тратьте время на div() Как и Nemo, компилятор легко оптимизирует использование деления, за которым следует использование модуля в одном. Напиши код, который имеет оптимальный смысл, и пусть компьютер удалит треск.