もしかしたら困ったときに開くとうれしいことがあるかもしれないヒント集

目次

剰余演算子

C言語には、割り算の余り(剰余)を求める演算子として、%があります。 例えば以下の記述では、13を10で割った余りである3がiに代入されます。
  i = 13 % 10;
なおこの余りの3は、「13」の一の位の数であることに注意しましょう。

ビット数と数値の限界

ビット数ととりうる値の範囲
ビット数 符号あり 符号なし
8bit -128〜+127 0〜255
16bit -32,768〜+32,767 0〜65,536
32bit -2,147,483,648〜+2,147,483,647
概ね -2×109〜+2×109
0〜4,294,967,296
概ね 0〜4×109

実数演算

実験用CPUボードのCコンパイラでは実数型 (floatとdouble) を使えません。 実定数や実数を扱う関数も使えません。

電圧1.3Vのように小数点以下1桁の実数値を扱いたい場合には、 10倍して整数演算すると良いでしょう。 100倍や1000倍でもかまいません。

実数を使おうとすると、以下のようなエラーになります。

*** FATAL ERROR L210: I/O ERROR ON INPUT FILE:
    EXCEPTION 0021H: PATH OR FILE NOT FOUND
    FILE: C:\KEIL\C51\LIB\C51FPS.LIB

べき乗

C言語では、べき乗を表現する演算子はありません。 LaTeXなどでは、「2^n」のように「^」を用いた記述でべき乗を表現できますが、 C言語では、この「^」は排他的論理和(ExclusiveOR)を表します。

演算子の優先順位

演算子の優先順位には、必ずしも直感とは一致しないものがあります。 詳細は、 「 【C言語講座】演算子一覧表」 などを参照。 自信がない時には括弧でくくってしまうと安全です。

引数を持たない関数

一般に、関数には、呼び出すときに与える値(引数)がありますが、 これをもたない関数を使う場合は、明示的に「引数がない」ことを 示す必要があります。 これは、次のように記述します。
char hoge(void) /* 関数の定義 */
{
...
}

main()
{
...
  a = hoge();   /* 関数の呼び出し */
...
}
前半の「char hoge(void) { … }」が関数の定義、 後半の「a = hoge();」が関数呼び出しです。

なお、

char hoge(void);

main()
{
  int a;
...
  a = hoge;   /* 関数へのポインタ (アドレス) */
...
}
もエラーにはなるとは限らないので注意してください。 hogeは関数へのポインタを返します。 関数を呼び出すhoge()とは異なります。

変数の宣言

変数の宣言は、ブロックの先頭で行う必要があります。 例えば、下記の「int b;」はエラー (Syntax error) になります。 最初の実行文「a = 0;」より前に置く必要があります。
int a;

main()
{
  a = 0;  // 最初の実行文

  int b;  // 「a = 0;」より後にあるのでエラー
以下のように、変数の宣言をブロックの先頭に書けばコンパイルできます。
int a;

main()
{
  int b;  // 最初の実行文「a = 0;」より前に書きます

  a = 0;  // 最初の実行文

シフト演算子

 シフト演算子「>>」や「<<」自体には、 変数の値を変化させる効果はありません。 例えば、「a << 1;」を実行しても、 変数「a」の値は変化しません。 変数「a」の値を変化させたい場合は、 「a <<= 1;」または「a = a << 1;」とします。
  int a;

  a = 1;
  num0= a;

  a << 1;
  num1 = a;

  a = a << 1;
  num2 = a;

  a <<= 1;
  num3 = a;

インデント

特にC言語でプログラムを記述するときには、次のように{}ごとに 適宜インデント(段そろえ)をすると、格段に読みやすくなります。
main()
{
  char i;
  for(i = 0; i < 10; i++){
    hoge(i);
  }
}
これは、あとでプログラムをデバッグしたり読み直すときに、 格段に効率が高くなるでしょう。

括弧の対応づけ

ある括弧がどの括弧と対応しているのかがわからなくなったときは、 その括弧にカーソルをあわせて、 「Edit」メニューの「Goto Matching Brace」を実行してみましょう。

もちろん、このような機能に頼らなくても済むように、 インデントをきちんとする、 コメントを書くなどの工夫をしておくことをお勧めします。

プログラムを変更しても反映されない

ソースプログラムを変更し、コンパイルし、転送しても、 CPUボードの動作が変わらないことがあります。 原因は多々あります。 代表的な事例には、下記があります。

プログラムの転送でエラーが起こる

 プログラムを転送しようとすると下記のようなエラーになる場合には、 USBケーブルを抜いて、もう一度挿し直してみましょう。 なお、CPUボードのリセットボタンを押すと、 このような症状になることがあるようです。
Toggle 8051 Reset
Failed to Open Driver
Reset Failed
指定されたファイルが見つかりません。

実験用CPUボードの動作がおかしい

プログラムを変更しても変更が反映されていない場合や、 理解不可能な挙動を示す場合で、 実験用CPUボードが誤動作していることもあります。 USBケーブルを抜いて挿し直せば正常に動作することがあります。 さらに、Windowsを再起動すれば正常に戻ることもあります。

ある電圧から動作がおかしくなります

前回動いていたプログラムが動かなくなりました

main()の先頭にある、CPUやI/Oポートを初期化する プログラムを削除すると、 マイコンをリセットまたは再起動すると動かなくなります。

main()
{
  // initialization
  CKCON |= 0x07; OEE = 0xef;
前回動作していたとすれば、この初期化をするプログラムを動かした後で、 問題のプログラムを動かしていたためでしょう。

プログラムを終了させたはずなのに最初に戻って繰り返します

今回使用するマイコンでは、 main()関数を終了させると予測不可能な動作をします。 再びmain()関数を実行し始めることが多いようです。 繰り返すのは、このためでしょう。

なお、main()関数を終了させると、 一見動いているようで、一部の機能がうまく動かないなど、 不可解なトラブルを起こすことがあります。 そのため、下記の無限ループは必ず残しておいてください。

main()
{
  // initialization
  CKCON |= 0x07; OEE = 0xef;
  led = 0; num0 = 10; num1 = 10; num2 = 10; num3 = 10;

  while(1){
    // write your code here
  }
}

急がば回れ

「わかったつもり」は、結局後で元に戻って理解しなおさねばならず、 しかも先入観がその理解の妨げになりかねません。

最初から、順番に手引書を読んでいくのが、結果として効率がよいことが 多いようです。

印刷

プログラムリストなどを印刷したいときは、Windowsの印刷機能を 用いれば可能です。 プリンタの設定ページを参考に設定するか、 「Brother HL-5380DN series」を選択してください。 プリンタは実験室の右前にあり、ネットワーク経由で接続されています。 なおプリンタの電源がONになっていることや用紙があることを確認しましょう。

 なお、「Microsoft Office Document Image Writer」 を指定しても印刷はできません。 「CubePDF」を指定すると、 紙に印刷するのではなく、PDFファイルを作成することができます。


戻る