[C言語入門]プリプロセッサ命令を理解する
今までの学習では、gccコマンドを使用してプログラムを作成してきました。 gccを使用すると、いきなり実行ファイル(.exeファイル)が生成されていたのですが、gcc(というかCコンパイラ)は内部的に以下の手順でexeファイルを作っています。 .cファイル ↓ プリプロセス ↓ .iファイル ↓ コンパイル ↓ .sファイル ↓ アセンブル ↓ .oファイル ↓ リンク ↓ .exeファイル.cファイル ↓ プリプロセス ↓ .iファイル ↓ コンパイル ↓ .sファイル ↓ アセン…
続きを読む
DDDデバッガで、ファイルをオープン時にNo Sourceのダイアログが出る時は
gccでコンパイルしたプログラムをデバッガであるdddでデバッグしようとした時、以下のエラーメッセージが表示されることがあります。 コンパイル&デバッガ起動のコマンド gcc -o test01 test01.c ddd ./test01gcc -o test01 test01.c ddd ./test01 エラーメッセージ DDD:No Source /gnu/gcc/releases/respins/4.5.3-3/gcc4-4.5.3-3/src/gcc-4.5.3/gcc/libgcc2.c:No such file or directoryDDD:No Source /gn…
続きを読む
[gcc最適化]printfがputs呼び出しに置き換えられる場合がある
C言語には、文字表示のためにprintf関数が有ります。 printfは%指定で変数を書式指定付きで埋め込める高機能な関数ですが、高機能な分、処理が遅いというデメリットもあり、書籍によっては “固定の文字を出すだけであればprintf()の替わりにputs()を使用すべし” というHowToが書かれてたりもします。 と今まで思ってましたが… gccの出力を見ると、時によっては”printfをputs呼び出しに自動で変換してくれる場合がある”ようです。 雰囲気では、printf( “hello\n” );のように、”変数を含…
続きを読む
cygwinで1秒未満のスリープを行う
C言語でプログラムを作成時にスリープ処理を行いたい場合、Cの標準ライブラリ関数だとsleep()関数を使用します。ですが、sleep()関数で指定する値の単位は秒なので、1秒未満のスリープを行う事が出来ません。 Visual C++等、Windows環境だとWin32APIにSleep()というものがあり、ミリ秒単位でのスリープが行えるのですが、cygwinでもこの関数が使用できるようです。 #include<stdio.h> #include<windows.h> int main() { printf( "t…
続きを読む
[C言語]getchar()関数は,1文字入力する毎に処理が走る訳ではない
C言語の入門書を見るとgetchar()関数の説明として、”キーボードから1文字入力を読み取る”と書かれていることが多いです。 下記のプログラムは、getchar()の動作確認用プログラムなのですが、実行してみると”キーボードから1文字入力を読み取る”という説明とは異なり、若干の違和感があります。 #inculde <stdio.h> int main( void ) { int data; while( 1 ) { // 1文字入力 data = getchar(); if ( data == EOF )…
続きを読む
[C言語]switch文のcase句の後にスペースが必要な場合/不要な場合
人が書いたプログラムを見ていたとき、switch文のcase句の書き方に違和感があるコードが有りました。 要点だけ抜粋すると、以下の内容です。 switch( data ) { … case’1′: // <- caseと’1’の間に空白がない!! … break; case’2′: … break; default: … break; } switch( data ) { … case’1′: // <- caseと’1’の間に空白がない!! … break; case’2′: … break; default: .…
続きを読む
[C言語入門]単純作業を繰り返しさせるためにfor文を使う
前回のプログラムでは、if文やswitch文を使って処理を分岐させる方法を学びました。 今回は、繰り返し処理を説明します。 プログラム言語において、繰り返し処理は、ループ処理とも呼ばれています。 コンピュータは大量の処理/データを、繰り返し作業させるのが得意です。 人とは違ってコンピュータは、どんなに大量のデータであっても途中であきらめずに作業してくれますし、途中で集中力が途切れて間違えてしまう事も有りません。 そんな繰り返し処理ですが、C言語に限らず、プログラムでのループ処理には大きく分けて2つのパターンがあります。 1.指定した回数繰り返す 2.指定した条件が満たされるまで繰り返す1.指定…
続きを読む
[C言語入門]複数の分岐をswitchでシンプルに記述する
前回、if文による処理の分岐を説明しました。 C言語によるプログラムではifさえあればあらゆる分岐は記述できるのですが、場合によってはifの羅列では分かり辛くなってしまう場合も有ります。 例えば、以下のようにメニューを用意し入力値を判定させる場合、比較対象は常にdataであるにも関わらず、毎回”data ==”を書かなければなりません。無駄な表記があると書き間違いが発生しやすくなりますし、ソースコードも見づらくなります。 #include <stdio.h> int main() { int data; …
続きを読む
[gcc]前置インクリメントと後置インクリメントで生成されるアセンブラコードの違い
今回のお題: 以下の文脈で、前置インクリメントと後置インクリメントを行った。 生成されるアセンブラコードは、iとjでどう変わるのか? #include <stdio.h> int main() { int i = 0; int j = 0; for ( i = 0, j = 0; i < 5 ; ) { printf( "ptn2 i = %d, j = %d\n", ++i, j++ ); } return 0; }#incl…
続きを読む
[C言語]printfの後の入力待ちで入力バッファがクリアされる理由
C言語の入門者向けに書かれた書籍を見ると、以下のようなプログラムが良く有ります。 #include<stdio.h> int main() { int value; printf( "数字を入力して下さい:" ); scanf( "%d", &value ); printf( "入力値は%dです\n", value ); return 0; }#include<stdio.h> int main() { i…
続きを読む
[C言語入門]処理の内容をif文で分岐させる
前回までのサンプルで確認したように、C言語のプログラムは基本的に上から書いた順に関数が実行されていく形で動作します。 一連の作業を順に行うだけならこれで構わないのですが、プログラムによっては状況に応じて処理を分岐したい場合も出てきます。 このような場合は、if文による処理分岐を行います。 というわけで、今回のサンプルはこちらです。 点数を入力し、60点以上なら合格、60点未満なら不合格と表示するプログラムです。 #include <stdio.h> int main() { int score; printf( &quo…
続きを読む
[gcc]if文と3項演算子では,出力されるコードが異なる
gccのアセンブラ出力を見ていて気になったのでメモ。 C言語ではif文を使わなくても、3項演算子を使用して条件分岐を “( a > b ) ? a : b”のような感じで書く事が出来ますが、両者の書き方で生成されるコードが異なるようでした。 3項演算子を使用した場合(test01.c) #include <stdio.h> int sum( int a, int b ); int main() { int a = 10; int b = 10; int result; result = &…
続きを読む
[C言語入門]変数が保持できる値の範囲について
変数の宣言 今回のサンプルでは、”int result”ということで、整数型の変数resultを定義しました。 変数として宣言できるのは,int以外にも以下のデータ型があります。 char 主に文字を格納するのに使用 int 主に整数を格納するのに使用 float 主に大きくない実数値を格納するのに使用 double 主に大きな実数値を格納するのに使用char 主に文字を格納するのに使用 int 主に整数を格納するのに使用 float 主に大きくない実数値を格納するのに使用 double 主に大きな実数値を格納するのに使用 また、intに関してはshort,longの接…
続きを読む
[C言語入門]計算した値を変数に保存する
前回は、指定された値を単に印字するだけのプログラムを作成しました。 コンピュータは日本語だと”電子計算機”と呼ばれるぐらいなので、今回は計算処理を行うプログラムを作成してみます。 今回のプログラムは以下の通りです。 #include <stdio.h> main() { int result; result = 10 + 20; printf( "result is %d\n", result ); }#include <stdio.h> main…
続きを読む
[C言語入門]printfの書式指定
前回のサンプルでは、printfの引数に%dを指定する事で、int型の変数値を表示させていました。 この%dの事を書式指定子(conversion specifier)と呼びます。 よく使用される書式指定子には以下のものがあります。 %の後に変換文字を書く事で表示方法を指定できます。 %d 整数を表示させる %s 文字列を表示させる %c 指定された文字コードに対応する,ASCII文字を1文字分表示させる %f 浮動小数点の値を表示(doubleまたはfloat) %d 浮動小数点の値を表示(double) %x 16進数で値を表示 %g 数字を指数表現で表示 %p ポインタ変数…
続きを読む
[C言語入門]画面にメッセージを表示させてみる
文法とか細かいことは置いといて、プログラムを1つ作ってみます。 作業は、windowsにインストールしたcygwin環境で行います。 まず、下記のファイルをエディタで作成します。 #include <stdio.h> main() { printf( "hello world\n" ); }#include <stdio.h> main() { printf( "hello world\n" ); } 作ったファイルは、以下のフォルダに保存してください。 (usernameの部分…
続きを読む
[gcc]long long intの値をprintfで表示させる
long long intで64bit整数値を格納した際に、その値をprintfで表示させる方法です。 普通に%dや%xで表示させようとしても、下位32bit分しか見てくれないので正しい値を表示させる事が出来ません プログラム #include <stdio.h> int main() { long long int a = (long long int)1 << 63; // NG: intとして表示 printf( "case1: %d\n", a ); &nb…
続きを読む
[パタヘネ][C]シフトと加算だけで、掛け算を行う
パタヘネの”第3章:コンピュータにおける算術演算”にある、3.3乗算の補足説明です。 “乗算は、ハードウェア的には、前述した加算処理とシフト処理で実装できる”を確認するために、Cでコードを作成しました。 当然ながら、乗算命令が下記のような形でソフトウェア的に実装されているというわけではないです。 下記のような振る舞いを行う”電子回路が組まれる”という意味だけど、 回路的として説明すると分かり辛いので、説明としてコードとして記述しただけです。 #include <stdio.h> main(…
続きを読む
cygwinでgcc開発メモ
cygwin環境の確認(win7, x64) $ uname CYGWIN_NT-6.1-WOW64$ uname CYGWIN_NT-6.1-WOW64 とりあえずhello world $ cat test01.c #include <stdio.h> main() { printf( "hello world\n" ); }$ cat test01.c #include <stdio.h> main() { printf( "hello world\n" ); } コンパイルしてexeの出力と実行 (cygwinでは、出力フ…
続きを読む
CとC++の非互換性:文字リテラルのサイズ
最近知った豆知識です。 CとC++で、以下のコードを実行したときの結果は異なります。 printf( "%d", sizeof(’A’) );printf( "%d", sizeof(‘A’) ); 実行してみると、Cでは4が表示され、C++だと1となります。 理由は、C言語の仕様上文字リテラルはintとみなされ、C++ではcharとみなされるから。 以下、仕様より An integer character constant has type int. The value of an integer char…
続きを読む