/ AOK's Home Page software / tips / source / javascript / links / profile / bbs / vector /
   

C言語ミニTIPS

Last Updated: Dec.8,2006
C言語でプログラミングする際のちょっとした情報。

LSI C-86 Ver.3.30c 試食版とBorland C++ 5.5について、プログラミングする際のちょっとした情報を記していきます。初心者向けを意識しているので、かなりアバウトな内容になると思います。まったくの初心者の方は「こんなこともあるんだ」くらいでも、いつか役に立つことがあるかもしれません。

ご意見・ご質問等は掲示板にてお願い致します。

  1. MS-DOSで使えるファイル名の制限
  2. getchar() で実行をストップして、表示内容を確認
  3. void main() と int main()
  4. プロトタイプ宣言
  5. メモリ・モデル
  6. 変数型のサイズ
  7. 構造体のアラインメント
  8. シフトJISコードにおける 0x5c(半角の¥)の問題

1. MS-DOSで使えるファイル名の制限

LSI C-86 Ver.3.30c 試食版は、16ビットコンパイラでありMS-DOS上で動作します。そのため、プログラミングする際には、MS-DOSの制約を受けることを念頭においておく必要があります。ここでは、使用できるファイル名について説明します。


2. getchar() で実行をストップして、表示内容を確認

printf() などを使って出力表示させることが多いプログラムでは、出力表示がどんどん流れていって、MS-DOS窓内で表示内容を確認できなくなることがあります。リダイレクトを使ってファイルにとる方法もありますが、出力表示を適当に区切って、止めたい個所に getchar() をはさむと簡単に解消できます。

/* getchar()で、Enterキーが押されるまで終了しない。*/
/* プログラムが完成したら、コメント化してしまえばよい。*/
printf("続行するには、エンター・キーを押す\n");
getchar();

*より確実に実行をストップさせるには以下のように、rewind(stdin); を実行して下さい。

/* getchar()で、Enterキーが押されるまで終了しない。*/
/* プログラムが完成したら、コメント化してしまえばよい。*/
printf("続行するには、エンター・キーを押す\n");
rewind(stdin);
getchar();

3. void main() と int main()

古い参考書では void main() が多く、新しいものでは int main() が多いようです。個人で学習する範囲においては、return する値に特に意味を持たせる(他のプログラムやバッチ処理で利用する)つもりがなく、コンパイラがエラーにならないのであれば、別にどっちでもよいように思います。ただし、void main() にしたときは値を返さず、int main() にしたときは必ず値(0でよい)を返しましょう。それが理解できていれば支障はないでしょう(ちなみに、私は int main() を使っています)。


4. プロトタイプ宣言

以下のプログラムを、LSI C-86 Ver.3.30c 試食版とBorland C++ 5.5でコンパイルしてみます。

#include <stdio.h>

void aisatsu()
{
    printf("Hello!\n");
}

int main()
{
    aisatsu();
    return 0;
}

LSI C-86 試食版では問題なくコンパイルできますが、Borland C++ 5.5では警告がでます。

警告 W8065 untitled.c 10: プロトタイプ宣言のない関数 'aisatsu' の呼び出し(関数 main )

これは単に警告なので、コンパイルには成功しています。しかし、気持ち悪い人もいるでしょうから、解消法を示します。

#include <stdio.h>

void aisatsu(void)
{
    printf("Hello!\n");
}

int main()
{
    aisatsu();
    return 0;
}

5. メモリ・モデル

LSI C-86 Ver.3.30c 試食版を使ってプログラミングしていると、

3.$$$ -32752: segment exceeds 64k

あるいは、

C:\LSIC86\LIB/s/cdos.obj(./cdos.p86), TEXT+0x0006: Overflow (word): HEAP
C:\LSIC86\LIB/s/cdos.obj(./cdos.p86), TEXT+0x0059: Overflow (word): HEAP
C:\LSIC86\LIB/s/cdos.obj(./cdos.p86), TEXT+0x0080: Overflow (word): HEAP
C:\LSIC86\LIB/s/cdos.obj(./cdos.p86), TEXT+0x00F4: Overflow (word): HEAP

などのエラーメッセージに出くわすことがあります。これは、LSI C-86 試食版が、16ビットコンパイラであり、かつ、スモールモデルでしかコンパイルできないという制限によるものです。スモールモデルというのは、コンパイラのメモリモデルのひとつです。詳しい説明を始めると長くなってしまうのと、私も多少曖昧なところがあるので、以下のサイトを参照してみてください。

しかし、このようなことがあるからと言って、LSI C-86 試食版が「使えない」ということではありません。むしろ、このような制限にひっかかるのであれば、プログラムそのものを考え直して、どのようにすればスモールモデルに納まるかを検討してみるとかなり勉強になると思います。


6. 変数型のサイズ

次のプログラムを両コンパイラでそれぞれコンパイル、実行してみます。

#include <stdio.h>

int main()
{
    printf("char: %2d bit\n",   sizeof(char) * 8);
    printf("short: %2d bit\n",  sizeof(short) * 8);
    printf("int: %2d bit\n",    sizeof(int) * 8);
    printf("long: %2d bit\n",   sizeof(long) * 8);
    printf("float: %2d bit\n",  sizeof(float) * 8);
    printf("double: %2d bit\n", sizeof(double) * 8);
    printf("void *: %2d bit\n", sizeof(void *) * 8);
    return 0;	
}

結果を表にして比較します。赤字の部分が相違点です。

  LSI C-86 試食版 Borland C++ 5.5
char 8 bit 8 bit
short 16 bit 16 bit
int 16 bit 32 bit
long 32 bit 32 bit
float 32 bit 32 bit
double 64 bit 64 bit
void * 16 bit 32 bit

また、char 型については、LSI C-86 試食版では符号無しの8ビット(0〜255)がデフォルトとなっていますが、Borland C++ 5.5 では、符号付きの8ビット(-128〜127)がデフォルトになっているので、注意が必要です。


7. 構造体のアラインメント

次の構造体のサイズを考えてみます。

struct DATA {
    char a;
    long b;
};

「6. 変数型のサイズ」で示した表から計算すると、両コンパイラとも、8 bit + 32 bit = 40 bit(5 バイト)となる筈ですが、実際に調べてみると、LSI C-86 試食版では、40 bit(5 バイト)となりますが、Borland C++ 5.5 では、64 bit(8 バイト)になります。これは、構造体の境界合わせの基準が、LSI C-86 試食版が 1 バイトであるのに対し、Borland C++ 5.5 では 4 バイトとなっているためです。このことは、構造体をファイルに書き込んだり、ファイルを読ン込んだりするときにかなり注意しなければいけません。


8. シフトJISコードにおける 0x5c(半角の¥)の問題

参考書によっては「\」(半角)と表記されているものです(当サイトでも表示フォントの関係でこう表示されていることが多いです)。この文字はC言語では改行などのエスケープ文字に使用され、MS-DOSやWindowsではディレクトリの区切り文字として使用されています。この「文字」というより「文字コード」が、私達が最もお世話になっている日本語の文字コードであるシフトJISコードにおいては、しばしば問題を引き起こします。というのも、漢字の中にこの文字コードが登場することがあるからです。

例を挙げます。

漢字
バイト位置 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2
コード(16進数) 83 5c 8d 5c 8f 5c 90 5c 93 5c 94 5c 95 5c 96 5c 97 5c

上記の表をみると、2バイト目が 0x5c となってい驍フがわかると思います。しかも、これらは頻繁に使用されるものです。この他にもあるのですが(「0x5C(\)を含む2バイト文字をリストする」を参照)、ここに挙げた文字くらいは覚えておくと役に立つ場面があるかもしれません。

具体的にどういう問題が生じるかと言いますと、

などです。実際、実用的なプログラムを書こうとすると、この問題にぶち当たることが多く、その為に余計なコード(笑)を書かなくてはなりません。

なお、このような問題はシフトJISコードを利用する日本語OSに依存していることなので、一般のC言語の教科書等では触れていない、あるいは、避けていることが多いかもしれません。また、アルゴリズムの説明やそのサンプル等では、わかりやすさを重視して省略していたりします。そのため、実用的なソフトを書く場合に、それらを不用意にまねたり、インターネットで海外からソースを引っ張ってきてそのまま使用したりすると、痛い目に遭うこともあります。


* LSI C-86 は、エル・エス・アイ ジャパン(株)の登録商標です。
* Borland C++ Compiler は、米国 Borland International Inc. の米国における登録商標です。

Top Copyright (c) 2003-2006 AOK. All Rights Reserved.