演習 3-4

無職の間にK&Rを再読。演習問題の解答をさらす。解く順番は適当。

演習 3-4
2の補数表現においては、われわれの itoa プログラムでは、最大の負の数、すなわち -(2wordsize-1) に等しい n の値が処理できない。なぜダメか説明せよ。また、計算機のいかんにかかわらずこの値を正確に印字するように、これを修正せよ。


Exercise 3-4
In a two's complement number representation, our version of itoa does not handle the largest negative number, that is, the value of n equal to -(2wordsize-1). Explain why not. Modify it to print that thw value correctly, regardless of the machine on which it runs.

説明せよ。2の補数表現で1バイトを表現したとき -128 から 127 までの範囲をとる、すなわち最大の負の数 -128 に対応する正の数 128 を表現できない。


負の数を正の数に変換するときに無理が生じるので、負の数は負の数のまま扱うことにした。

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

int abs(int n);
void reverse(char s[]);

/* Answer */
void itoa(int n, char s[])
{
  int i, sign;
  
  sign = n;
  
  i = 0;
  do {
    s[i++] = abs(n % 10) + '0';
  } while ((n /= 10) != 0);
  
  if (sign < 0)
    s[i++] = '-';
  
  s[i] = '\0';
  
  reverse(s);
}


int abs(int n)
{
  return n < 0 ? -n : n;
}


void reverse(char s[])
{
  int c, i, j;
  
  for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
    c = s[i];
    s[i] = s[j];
    s[j] = c;
  }
}


int main(void)
{
  int n;
  char s[100];
  
  n = INT_MAX;
  itoa(n, s);
  printf("%d [%s]\n", n, s);
  
  n = INT_MIN;
  itoa(n, s);
  printf("%d [%s]\n", n, s);
  
  return 0;
}