【c#】基本は、signed。意外と忘れガチ

今回は、超初歩的。(そもそもc#に限った話でもないw)

だから「バカにしとんか」くらいのひとはここでUターン推奨。


変数のデータ型を決めるとき、まれに忘れてるひとがいる《符号》の話ね。


たとえば。

整数データを扱うなら変数のデータ型は short か int をつかうことがおおい。

それぞれのサイズは、

・short → 16bit
・int → 32bit

だね。

で、「16bitだといくつくらいまで値が入るんだっけ?」って思ったとき、

0xff を10進に変換したりすると65535に変換される。

16bitだとマックスで65535まで扱えるんだな。と。

このとき、

「あー。どーせこの変数、めっちゃ入力されても50000くらいだから、shortでいいわ」

って考えると、バグるw

コード

using System;

namespace testNamespace
{
    class testClass
    {
        public void testMethod()
        {
            short shOutput = 0;

            // 15bit ON → 32767 / 16bit ON → 65535
            double[] dInput = {0, 32767, 65535};

            foreach(double d in dInput)
            {
                // 0, 32767, 65535 をshortに入れて表示してみる
                shOutput = (short)d;
                Console.WriteLine(shOutput);
            }
        }
    }
}

出力

0
32767
-1

65535 だったはずの値は -1 になってるね。

「いやいや、こんなドジしねーよ」って思うかもしれないけど、意外とよく見たらこーゆーコードはある。

そもそもデカい数値って入力される頻度がひくかったりするから、まちがったままリリースされて放置されがちなんだな。

言わずもがな、shortやintは《符号付き整数》。

最上位のbitは ± を表してるから、最上位のbitをたてても整数値は加算されない。

つーかマイナスの値になる。

コード

using System;

namespace testNamespace
{
    class testClass
    {
        public void testMethod()
        {
            short shOutput = 0;

            // 32768. 32769 のようなギリ16bitないと表現できない値を入れてみる
            double[] dInput = {0, 32767, 32768, 32769, 65535};

            foreach(double d in dInput)
            {
                shOutput = (short)d;
                Console.WriteLine(shOutput);
            }
        }
    }
}

出力

0
32767
-32768
-32767
-1

そりゃ、こーなるw

もし、shortのサイズ(16bit)で50000とか60000って値を格納したいならunsigned、すなわち《符号なし》にしよう。

・ushort
・uint

にすれば、全bitを数字につかえる。

まー逆にマイナスの値は扱えないけど。

コード

using System;

namespace testNamespace
{
    class testClass
    {
        public void testMethod()
        {
            ushort shOutput = 0;    // ← "unsigned"の'u'ね

            // 32768. 32769 のようなギリ16bitないと表現できない値を入れてみる
            double[] dInput = {0, 32767, 32768, 32769, 65535};

            foreach(double d in dInput)
            {
                shOutput = (ushort)d;
                Console.WriteLine(shOutput);
            }
        }
    }
}

出力

0
32767
32768
32769
65535


こんな超初歩的なことでも、超初歩的がゆえに見落とされてバグの温床になってる率は高い。

気をつけよーぜ。

これマジ。