web-dev-qa-db-ja.com

モジュラスを使用したC加算

A + Bを出力する興味深いCコードに出会いましたが、それを理解するのに苦労しています。

入力形式:

A B

ここで、ABは、単一スペースで区切られた010の間の整数です。

コード:

main( n )
{
    gets( &n );
    printf("%d", n % 85 - 43);
}

これは短いコーディングを目的としており、警告を気にしないでください。

私がこれまでに理解していること:

gets( &n )は、nの下位3バイトに、A、スペース、およびBのASCII値を格納します。たとえば、A = 3およびB = 8n = 0x00382033を生成します。与えられた条件は、nのオーバーフローを防ぎます。しかし、n % 85 - 43A + Bを生成する方法がわかりません。

これらの数字はどうやって思いつきますか?

80
William Lee

リトルエンディアンint(およびASCIIテキスト、8ビットバイト、およびコードが必要とする他のすべての仮定)を使用し、コード内の技術的に間違ったモダンCをすべて無視します。 、あなたの「これまでのところ私が理解していること」は正しい。

gets(&n)は、A、スペース、BのASCII値をnの最初の3バイトに格納します。また、ヌルターミネーターを4番目のバイトに格納します。これらのASCII値をnのそれらのバイトに格納すると、nが値B*256*256 + space*256 + Aを取ります。ここで、Bspace、およびAは対応するASCII値を表します。

256 mod 85は1なので、モジュラー演算の特性により、

(B*256*256 + space*256 + A) % 85 = (B + space + A) % 85

ちなみに、4バイトのビッグエンディアンのintでは、

(A*256*256*256 + space*256*256 + B*256) % 85 = (B + space + A) % 85

4バイトのintがあれば、エンディアンは関係ありません。 (より大きいまたはより小さいintが問題になる可能性があります。たとえば、8バイトのintでは、nが設定しなかったgetsのバイトに何があるかを心配する必要があります。)

スペースはASCII 32で、数字のASCII値は48 +数字の値です。 aおよびbを、入力された数字の数値(数字のASCII値ではなく)として定義すると、

(B + space + A) % 85 = (b + 48 + 32 + a + 48) % 85
                     = (a + b + 128) % 85
                     = (a + b + 43) % 85

(B + space + A) % 85 - 43 = (a + b + 43) % 85 - 43
                          = (a + b) % 85
                          = a + b

ここで、最後の2つの等価性は、aおよびbが0から9までの値を取るという事実に依存しています。

87
user2357112