C言語の記号定数「EOF」を使うときの心構え

「プログラミング言語C」という書籍に書かれていた内容で印象に残ったコトの話です。まずは以下のソースを見てください。


#include <stdio.h>

int main(void)
{
	int c;

	c = getchar();
	while( c != EOF )
	{
		putchar(c);
		c = getchar();
	}
	printf("終了\n");
}

キーボードで打った文字をディスプレイ画面に表示するだけのプログラムです。EOFを検知するとプログラム終了となります。Linux環境だとEOFはキーボードで「ctrl」+「D」(同時に押す)を入力します。実行結果は以下です。

$ ./a.out
a
a
x
x
終了
$

このときは「a」を入力してリターンキー押下、「x」を入力してリターンキー押下、そして「ctrl」+「D」の入力をしました。

さて、最初のプログラムソースですが違和感とかありますでしょうか?

僕は特になかったです(というかまったく気づいていませんでした)。何を気にするかというと、変数「c」の型です。cには文字が格納できればいいわけですから、intと宣言しなくてもcharで事足りるのでは?ということです。キーボードからの1文字を入力して、ディスプレイにその1文字を表示しているだけですから。実際に変数cの宣言をchar型に変更して同じようにやってみたところ、結果は全く同じでした。

でも、intで宣言する理由がちゃんとあったのです。それは記号定数「EOF」が、はたしてどんな値なのか?ということによります。つまり1バイトしかないchar型でEOFを格納できるのか?ということです。もしEOFが1バイトで収まらなかった場合、桁溢れを起こしてしまいますのでwhileの終了条件にはいつまでたっても合致しません。そのためEOFが収まる十分大きなint型として変数cを宣言していたのです。

では、charとintでどれだけ大きさの違いがあるのかを確認するためlimits.hを見てみました。以下はlimits.hからの抜粋です。


/* Minimum and maximum values a `signed char' can hold.  */
#  define SCHAR_MIN     (-128)
#  define SCHAR_MAX     127

/* Maximum value an `unsigned char' can hold.  (Minimum is 0.)  */
#  define UCHAR_MAX     255

/* Minimum and maximum values a `signed int' can hold.  */
#  define INT_MIN       (-INT_MAX - 1)
#  define INT_MAX       2147483647

/* Maximum value an `unsigned int' can hold.  (Minimum is 0.)  */
#  define UINT_MAX      4294967295U

64ビットOSのLinux(ubuntu)を使用しているのですが、charは1バイト、intは4バイト(2の32乗)の領域を確保しています。ただ先にも書いたように変数cはchar型でも問題なく動きました。EOFの値が何なのかを調べることは可能で、実際に計算させるか、stdio.hにEOFが定義されているのでそれを見るか、です。

実際に計算させるには以下のソースをコンパイルして実行します。


#include <stdio.h>

int main(void)
{
	printf("EOF is %d\n", EOF);
}

結果は「EOF is -1」と表示されます。stdio.hを見てみるとEOFの定義があります。以下は抜粋です。


/* End of file character.
   Some things throughout the library rely on this being -1.  */
#ifndef EOF
# define EOF (-1)
#endif

結果を言うと、EOFは「-1」だからcharでも問題ないわけですね。ただ、EOFは「-1」と覚えてしまうのは危険です。というのもLinux環境の場合、OSがEOFを検知した際にプログラムに「-1」を返すだけであって、他の機種やOSの場合は異なる可能性があるからです。ですから、EOFが収まるであろう十分大きな型であるintを使っているということでしょう。なお「-1」というのはASCII文字コード上には表れない値なので、OSがEOFの印として使っているのでしょう。

ちなみに、記号定数「NULL」についても書いておきます。NULLは通常0(数字のゼロ)なのですが、これは数値ではなくポインタアドレスの位置であって、位置がゼロ(すなわちアドレスがない)ということになります。数字と考えるよりアドレスがあるかないかの印と思ったほうが良いです。なので、NULLを数値のゼロと思ってポインタでない変数の条件式(等号、不等号とか)で使うのはやめましょう。

ubuntuにzoomクライアントを入れてみた。

ubuntuでもzoomが使えるようなので、ubuntu18.04 LTS にzoomクライアントをインストールしてみました。まずはzoomのダウンロードページに行きます。

zoomのダウンロードセンター

僕のPCではLinuxタイプには「Ubuntu」を、OSアーキテクチャには「64ビット」を、バージョンには「14.04+」を選択しました。ダウンロードボタンの右隣に小さく薄い字でバージョンが示されていますが、2020/7/11時点では「バージョン5.1.422789.0705」となっています。

ダウンロードボタンを押下するとhomeディレクトリのダウンロード配下にパッケージがダウンロードされるので確認してみます。


$ pwd
/home/khst/ダウンロード
$ ls -l
合計 40960
-rw-rw-r-- 1 khst khst 41940564  7月 11 00:03 zoom_amd64.deb
$ 

このzoomクライアントのパッケージを「apt install ./zoom_amd64.deb」でインストールします(rootにsuするか、sudoコマンドを使用します)。以下がインストールした際のログです。


# apt install ./zoom_amd64.deb
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
注意、'./zoom_amd64.deb' の代わりに 'zoom' を選択します
以下の追加パッケージがインストールされます:
  libxcb-xtest0
以下のパッケージが新たにインストールされます:
  libxcb-xtest0 zoom
アップグレード: 0 個、新規インストール: 2 個、削除: 0 個、保留: 14 個。
41.9 MB 中 4,820 B のアーカイブを取得する必要があります。
この操作後に追加で 157 MB のディスク容量が消費されます。
続行しますか? [Y/n] Y
取得:1 /home/khst/ダウンロード/zoom_amd64.deb zoom amd64 5.1.422789.0705 [41.9 MB]
取得:2 http://jp.archive.ubuntu.com/ubuntu bionic-updates/main amd64 libxcb-xtest0 amd64 1.13-2~ubuntu18.04 [4,820 B]
4,820 B を 2秒 で取得しました (2,205 B/s)                          
以前に未選択のパッケージ libxcb-xtest0:amd64 を選択しています。
(データベースを読み込んでいます ... 現在 168236 個のファイルとディレクトリがインストールされています。)
.../libxcb-xtest0_1.13-2~ubuntu18.04_amd64.deb を展開する準備をしています ...
libxcb-xtest0:amd64 (1.13-2~ubuntu18.04) を展開しています...
以前に未選択のパッケージ zoom を選択しています。
.../zoom_amd64.deb を展開する準備をしています ...
zoom (5.1.422789.0705) を展開しています...
libxcb-xtest0:amd64 (1.13-2~ubuntu18.04) を設定しています ...
zoom (5.1.422789.0705) を設定しています ...
run post install script, action is configure...
desktop-file-utils (0.23-1ubuntu3.18.04.2) のトリガを処理しています ...
libc-bin (2.27-3ubuntu1.2) のトリガを処理しています ...
shared-mime-info (1.9-2) のトリガを処理しています ...
gnome-menus (3.13.3-11ubuntu1.1) のトリガを処理しています ...
mime-support (3.60ubuntu1) のトリガを処理しています ...

インストールしたパッケージを確認してみます。


# dpkg -l | grep zoom
ii  zoom                                       5.1.422789.0705                                  amd64        Zoom, #1 Video Conferencing and Web Conferencing Service 

デスクトップのアクティビティを見てみると、zoomのアイコンが出来ているのがわかります。

zoomのアイコンをクリックして以下の画面が立ち上がればzoomクライアントはインストールできています。

ubuntuでzoomミーティングに参加しましたが問題なかったです。

ちなみに、初期設定だとメニューやボタンの表示が英語になっているので、日本語にするにはzoomのサポートページを参照ください。初期設定のままでも参加者の名前は日本語表示されるので日本語が使えないわけではないです。

[2023/05/27 追記]
久しぶりにubuntuのZOOMを使ってみたら、使えなくなっていました。バージョンが古いらしいです。ダウンロードサイトから新しいdebファイルをダウンロードして、アップグレードをしました。

# apt upgrade ./zoom_amd64.deb

アップグレード後のパッケージのバージョンです。


# dpkg -l | grep zoom
ii  zoom                                       5.14.7.2928                         amd64        Zoom Cloud Meetings

アップグレード前が 5.1.422789.0705 だったから、結構変わっていました。また、アップグレード後のZOOMのアイコンも変わっていました。

アップグレード後は、ZOOMミーティングに参加できるようになりました。

なおZOOMの日本語化ですが、ZOOMを起動して右上のZOOMアイコンから変更できます。