All posts by chen

[GCC]C Compiler on Linux

C言語の最小限の開発環境を作る手順

  1. エディタをインストール
  2. コンパイラをインストール
  3. コンパイラにPATHを通す設定をする

エディタをインストール

Atomという新世代のエディター(Windows、Mac OS X、Linux対応)をインストールしてください。

公式サイト

コンパイラをインストール

LinuxでのC言語開発環境について解説しています。「GNU Compiler Collection」が一般的です。

それでは gcc をインストールしていきます。

Debian

Debianでは、apt-getコマンドを使ってgccをインストールします。

# apt-get install gcc

Ubuntu

UbuntuはDebianベースのディストリビューションなので、Debianと同じようにa apt-getコマンドを使います。ただ、Ubuntuにはrootユーザーという概念がないので、sudoコマンドでインストールしていきます。

$ sudo apt-get install gcc

CentOS

CentOSでは、yumコマンドを使ってgccをインストールします。

# yum install gcc

以上で、コンパイラ(gcc)のインストールは完了です。

コンパイラにPATHを通す設定をする

不要です。

ソースコードコンパイル

C言語プログラムのファイル名を「hello.c」というファイルを作成します。ファイルの中身は「Hello, World!」という文字列を出力するプログラムです。

hello.cをコンパイルします。

$ gcc hello.c 

エラーが表示されなければ、OKです。

プログラムの実行

実行します。

$ ./a.out 
Hello, World

無事に実行できましたね。

[GCC]C Compiler on Windows

WindowsでgccをインストールするにはMinGWを利用した、C言語の最小限の開発環境を作る手順

  1. エディタをインストール
  2. コンパイラをインストール
  3. コンパイラにPATHを通す設定をする

エディタをインストール

AtomVSCodeなど新世代のエディター(Windows、Mac OS X、Linux対応)をインストールしてください。

コンパイラをインストール

C言語コンパイラって幾つかありますが、visual studioはファイルサイズがデカいので却下です。gccのインストールをオススメします。gccはMacでもLinuxでもWindowsでも使えます。

コンパイラの違い一覧

システム mingw-jp Visual Studio .net Borland C++ Builder
コンパイラ名 gcc cl bcc32
オブジェクトファイルの拡張子 .o .obj .obj
実行ファイル名指定 -o ファイル名 -o ファイル名 -eファイル名
make コマンド mingw32-make nmake make
依存ファイルマクロ $^ $** $**

 

WindowsでgccをインストールするにはMinGWというソフトを使う必要があります。

MinGW | Minimalist GNU for Windows

  1. MinGWのホームページで「Downloads」をクリック
  2. sourceforgeというサイトに飛びます
  3. 「Download mingw-get-setup.exe (86.5 kB)」をクリック
  4. exeファイルをダウンロード
  5. ダウンロードしたexeファイルを起動
  6. インストール自体は「Install」ボタンとか「Continue」ボタンをクリックするだけ

MinGW インストールマネージャー画面 4

左のメニュー画面で「Basic Setup」を選択し、

  • mingw-developer-toolkit
  • mingw32-base
  • mingw32-gcc-g++
  • msys-base-32

を選んで、右クリックで「Mark for Installation」を選択します。

選び終わったら、上の「Installation」メニューから「Apply Changes」を選択すればインストールが始まります。

インストールが始まると、先ほど選択したパッケージがこのように変わります。

MinGW インストールマネージャー画面 5

これでGCCが使えるようになりました。

コンパイラにPATHを通す設定をする

事前にgcc.exeの場所を探しておいてください。
MinGWをインストールする際に設定を変更していなければ C:MinGWbin にあるはずです。

  • エクスプローラー起動
  • マイコンピューターで右クリック
  • プロパティ選択
  • システムの詳細設定
  • 「環境変数」ボタン
  • ユーザー環境変数 or システム環境変数にPathがあります
    そのPathの最後に ;C:¥MinGW¥bin を追記
    ※「;」を必ず付けてください

環境変数画面

ユーザー環境変数とシステム環境変数の違い

  • ユーザー環境変数:今ログインしているユーザーだけに有効
  • システム環境変数:全てのユーザーに有効

お好きな方をお使いください。

コマンドプロンプトで gcc --help と打ってみてください。

↓こんな感じのものが出てればgccが正常に使える状態です。

 

バージョンの確認

> gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/5.3.0/lto-wrapper.exe
Target: mingw32
Configured with: ../src/gcc-5.3.0/configure --build=x86_64-pc-linux-gnu --host=mingw32 --prefix=/mingw --disable-win32-registry --target=mingw32 --with-arch=i586 --enable-languages=c,c++,objc,obj-c++,fortran,ada --enable-static --enable-shared --enable-threads=posix --with-dwarf2 --disable-sjlj-exceptions --enable-version-specific-runtime-libs --enable-libstdcxx-debug --with-tune=generic --enable-libgomp --disable-libvtv --enable-nls
Thread model: posix
gcc version 5.3.0 (GCC)

 

ソースコードコンパイル

C言語プログラムのファイル名を「hello.c」というファイルを作成します。ファイルの中身は「Hello, World!」という文字列を出力するプログラムです。

以下のコマンドを打ってみてください。

> gcc hello.c -o hello.exe

そしたら hello.exe が作られています。

プログラムの実行

コマンドプロンプトで実行ファイル名を入力してEnterキーを押すだけです。

コマンドプロンプトで、「hello.exe」を実行します。

> hello.exe
Hello, World

このように「Hello, World」という文字列が出力されれば、OKです。

実行ファイルを指定した場合、指定したファイルを実行してください。

参考:

C exercises2 (3) structures

演習

1)任意二つのunsigned int型数値の論理AND, OR, XORを求めなさい(P324)

/* a9-4-1.c */
#include <stdio.h>
#include <limits.h>

int main(void)
{
  unsigned a, b;

  printf("0 〜 %u の整数を2つ入力してください。¥n", UINT_MAX);
  printf("> ");
  scanf("%u", &a);
  printf("> ");
  scanf("%u", &b);

  printf("%u(%#x) AND %u(%#x) = %#x¥n",__,__,__,__,__);
  printf("%u(%#x) OR  %u(%#x) = %#x¥n",__,__,__,__,__);
  printf("%u(%#x) XOR %u(%#x) = %#x¥n",__,__,__,__,__);

  return 0;
}

 

2)任意unsigned int型数値のビットパターンを表示(P328)

/* a9-4-2.c */
#include <stdio.h>
#include <limits.h>

void show_bit(unsigned dt);

int main(void)
{
  unsigned a;

  printf("0 〜 %#x の16進数を入力してください。> ", UINT_MAX);
  scanf("%x", &a);

  show_bit(a);

  return 0;
}

/*** ビット表示関数 ***/
/*(仮引数)dt:表示データ */
void show_bit(unsigned dt)
{
    int i, len;

    len = sizeof(dt) * CHAR_BIT;
        
    printf("%#x ---> ", dt);
    for (i = len - 1; i >= 0; i--){
        putchar(( __ >> __ & 1U) ? '1' : '0' );
    }
    putchar('¥n');
}

 

演習解説

構造体の変数

構造体とは

構造体とは,「いろいろな種類の互いに関連するデータをまとめて, 1つのかたまりにしたもの」である。 たとえば,「氏名,年齢,性別などのデータを一人分だけまとめたもの」 このようなものをいう。

構造体 構造体を構成する要素を,構造体のメンバと呼ぶ。上の例では, 「名前」「性別」「年齢」「身長」「体重」などが,メンバにあたる。

構造体の宣言

構造体は,一つのデータ型であり,その型枠をまず始めに宣言する必要がある。 そして,その型枠を型とする変数を宣言する形で構造体の実体(オブジェクト)を宣言し, それを使用することができる。

構造体の型枠の宣言と,その型枠をもつ構造体変数の宣言は次のようになされる.

struct 構造体タグ名 {メンバの並び};   /* 型枠の宣言 */

struct 構造体タグ名 構造体変数名;     /* 構造体変数の宣言 */

例えば,次図のような人のデータをまとめた構造体の定義は下のようになる。

person 構造体struct

 _person {           /* _person がタグ名 */
    char name[20];        /* 文字配列型のメンバ name */
    char sex;              /* 文字型メンバ sex */
    int age;               /* 整数型メンバ age */
    double height;         /* 倍精度実数型メンバ height */
    double weight;         /* 倍精度実数型メンバ weight */
};


struct

 _person p;      /* p という名前の struct _person 型変数を宣言 */

構造体の代入

一つの構造体変数の内容全部を 同じ型の別の構造体変数に, 通常の変数を代入するのと同じように,代入することができる.

    person_t p1 = {"Tom", 'M', 19, 175.2, 69.5};
    person_t p2;
    
    p2 = p1;

構造体の代入

構造体の配列

構造体を並べた配列も扱える.その宣言定義は通常のようにすればよい.

#define PERSON_NUM 5

typedef struct {   
    char name[20];
    char sex; 
    int age;
    double height; 
    double weight; 
} person_t;

person_t p[PERSON_NUM]

;

これで,要素数がPERSON_NUM個(5個)の person_t 構造体型配列 p ができる.

構造体配列たとえば,上の図で色のついてある p[3] の height メンバには, p[3].height でアクセスする.

サンプルプログラム2

#include <stdio.h>

#define PERSON_NUM 5

typedef struct {   
    char name[20];
    char sex; 
    int age;
    double height; 
    double weight; 
} person_t;

main()
{
    person_t p[PERSON_NUM] = {{"Bob",      'M', 19, 165.4, 72.5},
                              {"Alice",    'F', 19, 161.7, 44.2},
                              {"Tom",      'M', 20, 175.2, 66.3},
                              {"Stefany",  'F', 18, 159.3, 48.5},
                              {"Leonardo", 'M', 19, 172.8, 67.2}};
    int i;
    double height_sum, weight_sum, height_ave, weight_ave;                          
    
    height_sum = weight_sum = 0.0;
    for (i = 0; i < PERSON_NUM; i++) {
        height_sum += p[i].height;
        weight_sum += p[i].weight;
    }
    height_ave = height_sum / PERSON_NUM;
    weight_ave = weight_sum / PERSON_NUM;
    
    printf("average height = %fn", height_ave);
    printf("average weight = %fn", weight_ave);
    
    return 0;
}

構造体のいろいろな宣言の仕方

  1. 構造体の型枠と実体を同時に宣言する
  2. 初期化も同時に行う
  3. 構造体タグ名を記述しないこともできる
  4. typedefで別名をつけることができる

演習

「学籍番号、氏名、学年、クラス」を含める構造体の宣言、初期化、表示するプロフラムを作る。
演習
struct student
{
char no[10]; //番号
char name[20]; //名前
int s_year; //年
char s_class; //クラス
};

C programming 2 (3) Arrays 2

ハッカソン

ハッカソン(英語: hackathon 、別名:hack day ,hackfest ,codefest )とはソフトウェア開発分野のプログラマやグラフィックデザイナー、ユーザインタフェース設計者、プロジェクトマネージャらが集中的に作業をするソフトウェア関連プロジェクトのイベントである。

ハッカソン – Wikipedia

https://ja.wikipedia.org/wiki/ハッカソン

国内最大級のITコンテスト「JPHACK 2016」のお知らせ
——————————————————————————

こんにちは!JPHACKS運営事務局です。

突然ですが、モノづくりを仕事にしたいと考えているデザイン系、情報系学生のみなさん、
こんなお悩みはありませんか?

・「学生のうちに、アプリやプロダクトなど何か一つ形にしておきたい」
・「ただ、自分は○○はできるけど、△△ができないから、Webサービスやアプリをつくれない」
・「同世代のデザイン系学生、情報系学生と競い合い、交流したい」
・「自分のスキルがどの程度のものか確かめたい。有名企業の社会人からレビューを受けてみたい」

そんなお悩みを解決すべく今回ご紹介させていただくのが、「JPHACKS 2016」です。

http://jphacks-civic.strikingly.com/

JPHACKS2016 エントリーの歩み:

  1. JPHACKS2016 エントリー
  2. JPHACKS2016 本エントリー
    1. URL: http://ubi.daiichi-koudai.com/ – ユビキタス・クラブ
    2. github: https://github.com/
  3. JPHACKS2016追加エントリー

前回の演習

  • 演習5-4(p115) List5-6を書き換えて、配列aの要素の並びを逆順にしたものをbにコピーするプログラムを作成さよ。
#include <stdio.h>
#define NUMBER 5

int main(void)
{
    int i;
    int va[NUMBER] = {15, 20, 30};
    int vb[NUMBER];
    
    for(i = 0; i < 5; i++) {
        vb[i] = va[NUMBER - i - 1];
    }
    
    puts(" va vb");
    puts("-------");
    
    for(i = 0; i < 5; i++) {
        printf("%3d%3d\n", va[i], vb[i]);
    
    }
    
    return(0);
}

 

二次元配列の宣言

配列には同じデータ型の値を要素として管理できますが、配列そのものを要素として持つ配列を作成することが出来ます。何次元でも出来ますがよく利用される2次元を例に考えてみます。

2次元配列の書式は次の通りです。

データ型 配列名[要素数1][要素数2];

配列と単に書いた場合は1次元の配列です。1次元の配列の場合は「配列名[添字]」でそれぞれの要素を表しますが、2次元の場合は「配列名[添字][添字]」で各要素を表します。

具体的には次のように記述します。

int seiseki[2][3];

seiseki[0][0] = 72;
seiseki[0][1] = 67;
seiseki[0][2] = 84;

seiseki[1][0] = 67;
seiseki[1][1] = 92;
seiseki[1][2] = 71;

2次元配列を使う意味を考えてみます。例えば6日間の運動した時間を管理するのではあれば1行に列挙して管理するのが便利ですし、3教科の成績を2人分管理するのであれば表形式で管理した方が便利です。成績と名前などのように2つの異なるインデックスを使って要素を特定した方が便利な場合には2次元配列が有効です。

なお今回は2次元の例でしたが3次元でも4次元でも可能です。その場合は次のような書式となります。

データ型 配列名[要素数1][要素数2][要素数3];
データ型 配列名[要素数1][要素数2][要素数3][要素数4];

3次元までは利用することもありますが、4次元以上の多次元配列ともなるとあまり利用する機会はありません。

二次元配列の初期化

二次元配列の場合でも宣言と同時に初期値を設定することが出来ます。次の書式を使います。

データ型 配列名[要素数1][要素数2] = {{値00, 値01, ...}, {値10, 値11, ...}, ...};

少し分かりにくいですが上記は次のように記述したものと同じです。

データ型 配列名[要素数1][要素数2];

配列名[0][0] = 値00;
配列名[0][1] = 値01;
...


配列名[1][0] = 値10;
配列名[1][1] = 11;
...

...

要素数2の配列があたかも1つの要素のように、要素数1の分だけあるような形で指定します。具体的には次のように記述します。

int seiseki[2][3] = {{72, 67, 84}, {67, 92, 71}};

この場合は次のように記述した場合と同じです。

int seiseki[2][3];

seiseki[0][0] = 72;
seiseki[0][1] = 67;
seiseki[0][2] = 84;

seiseki[1][0] = 67;
seiseki[1][1] = 92;
seiseki[1][2] = 71;

要素数を指定せずに初期化する

配列は宣言と同時に初期化する場合は要素数を省略できました。2次元配列の場合でも最初の配列の要素数は省略が可能となっています。

データ型 配列名[][要素数2] = {{値00, 値01, ...}, {値10, 値11, ...}, ...};

具体的には次のように記述します。

int seiseki[][3] = {{72, 67, 84}, {67, 92, 71}};

二次元配列のデータの利用

では簡単なサンプルプログラムを作成して試してみます。

test5-1.c

#include <stdio.h>

int main(void){
  int seiseki[][3] = {
    {72, 67, 84}, 
    {67, 92, 71}
  };
  int i;

  for (i = 0 ; i < 2 ; i++){
    printf("%d人目の成績です¥n", i + 1);
    printf("算数の点数は%dです¥n", seiseki[i][0]);
    printf("国語の点数は%dです¥n", seiseki[i][1]);
    printf("社会の点数は%dです¥n", seiseki[i][2]);
  }

  return 0;
}

上記を「test5-1.c」の名前で保存し、実行します。

演習

test5-1.cを修正して、科目ごとの合計点を求めてください。

出力例:

算数の合計点:289
国語の合計点:293
社会の合計点:292

C exercises2 (2) bitwise

第9章 ビットを意識する

整数型の指定

整数値を扱うための型には,( signed, unsigned ) char 型と int 型とがあることは説明したが, それら以外にもある.ここで,まとめて簡単に解説する.

バイト数 ビット数 最小値 最大値
unsigned char 1 8 0 255
signed char 1 8 -128 127
unsigned short int 2 16 0 65535
signed short int 2 16 -32768 32767
unsigned int 4 32 0 4294967295
signed int 4 32 -2147483648 2147483647
unsigned long int 4 32 0 4294967295
signed long int 4 32 -2147483648 2147483647
unsigned long long int 8 64 0 18446744073709551615
signed long long int 8 64 -9223372036854775808 9223372036854775807

基本的な整数型には char, short int , int, long int, long long int の4種類があり,そのサイズは char ≦ short int ≦ int ≦ long int ≦ long long int となる.

char 型は 1 バイトであると決まっているが,あとの種類はサイズが厳密に決められたものではなく, 将来は変わる可能性がある. 実際に,数年前のパソコンは 16ビットマシンが多かったので, int 型は 16ビット=2バイトであった.

今使っているコンピュータの環境では,たまたま int 型と long int 型とは,まったく同じものとなっている.

浮動小数点型の指定

 

バイト数 ビット数 最小値 最大値
float 4 32 1.175494 10-38 3.402823 10+38
double 8 64 2.225074 10-308 1.797693 10+308

 

float型

float型は4バイト=32ビットのサイズを持ち,そのビットを次のように,符号,指数,仮数を表すために用いる.

float型の内部表現指数部-127 が指数の値となる.仮数部は仮数の小数点以下を表している.すなわち,仮数は仮数部の先頭に 1. を付加したものになる.

 

float の表す値 = (-1)符号部 × 2指数部-127 × 1.仮数部

float 型の精度(有効桁数)は2進数にして 24 (=23+1) 桁であり,10進数では約 7 桁となる.

double 型

float 型に比べて,約倍の精度をもった浮動小数点型の型が double である. double 型は 8バイト=64ビットのサイズであり,その内部表現は次のようになる.

double型の内部表現指数部-1023 が指数の値となる.仮数部は仮数の小数点以下を表している.すなわち,仮数は仮数部の先頭に 1. を付加したものになる.

 

double の表す値 = (-1)符号部 × 2指数部-1023 × 1.仮数部

double 型の精度(有効桁数)は2進数にして 53 (=52+1) 桁であり,10進数では約 15 桁となる.

Sizeof演算子

簡単に言うと,sizeofに渡された型や変数のメモリサイズを調べるものです.

sizeof演算子は2種類の使い方があります.

  • sizeof(型)
  • sizeof 変数や定数,あるいは式など

ビット演算子

ビット単位でデータ操作をするものです。対象は整数に限られます

【ビット演算子】
演算子 説明
 & ビットごとの AND
 | ビットごとの OR
 ^ ビットごとの XOR
 ~ ビットごとの反転(1 の補数)
 << 左シフト
 >> 右シフト

(1) & (and)

両方のビットが 1 のときのみ結果が 1 になるビット演算です。

0 & 0 → 0
0 & 1 → 0
1 & 0 → 0
1 & 1 → 1

必要なビット以外をOFF(0)にする処理(マスクといいます)に使用されます。

例えば、10101010 という1バイトのビット列の下位4ビットを OFF する場合、そのままにしたいビットを 1 、OFFしたいビットを 0 にした、11110000 で and することにより実現できます。

(使用例)

unsigned char a = 0xaa;	/*     10101010 */
printf("%#xn",a & 0xf0);	/* and 11110000 */

実行結果
0xa0

(2) | (or)

いずれかのビットが 1 なら結果が 1 になるビット演算です。

0 | 0 → 0
0 | 1 → 1
1 | 0 → 1
1 | 1 → 1

必要なビットをON(1)にする場合に or は使われます。

例えば、10101010 という1バイトのビット列の上位4ビットを ON する場合、ONにしたいビットを 1 、そのままにしたいビットを 0 にした、11110000 で or することにより実現できます。

(使用例)

unsigned char a = 0xaa;	/*    10101010 */
printf("%#xn",a | 0xf0);	/* or 11110000 */

実行結果
0xfa

(3) ^ (xor)

両方のビットが異なるときに結果を 1 にするビット演算です。

0 ^ 0 → 0
0 ^ 1 → 1
1 ^ 0 → 1
1 ^ 1 → 0

特定なビットを反転する場合に xor は使われます。

例えば、10101010 という1バイトのビット列の下位4ビットを反転する場合、反転したいビットを 1 、そのままにしたいビットを 0 にした、00001111 で xor することにより実現できます。

(使用例)

unsigned char a = 0xaa;	/*     10101010 */
printf("%#xn",a ^ 0x0f);	/* xor 00001111 */

実行結果
0xa5

(4) ~ (補数)

ビットの反転を行うビット演算です。

0 → 1
1 → 0

全ビットの無条件反転を行います。

(使用例)

unsigned char a = 0xaa;	/*     10101010 */
printf("%#xn",~a);

実行結果
0xff55		
(注)printf関数が unsigned char型を int型に符号拡張するために、0xff55 と表示されます。
   int型が4バイトの処理系では 0xffffff55 になります。

(5) << (左シフト)

x << n と書き、x を n ビット左へシフトします。

右側の空いたビットには 0 が入り、左側のビットは捨てられます。

左シフトは x が正の場合、x << 1 で「x * 2」を計算することと同じになります。

(例)

正の整数のとき

int x = 100;

x = x << 2;

(6) >> (右シフト)

x >> n と書き、x を n ビット右へシフトします。

左側の空いたビットには、x が符号無しなら 0 が入ります。x が符号付きなら、算術シフトを行う処理系では符号桁が入り、論理シフトを行う処理系では 0 が埋められます。 右側のビットは算術シフト、論理シフトにかかわらず捨てられます。

右シフトは x が正の場合 x >> 1 で「x / 2」を計算することと同じになります。

(例)

正の整数のとき

int x = 100;

x = x >> 2;

負の整数のとき(算術シフトを行う処理系の場合)

int x = -100;

x = x >> 2;

【参考】

  • 算術シフト:数値の演算を行うときに使用するシフト演算で、シフトの際に最上位の符号ビットを保存するシフトです。
  • 論理シフト:ビットの位置を変えるときに使用するシフト演算で、シフトの際に最上位の符号ビットを考慮することなくシフトを行います。

演習

1)任意二つのunsigned int型数値の論理AND, OR, XORを求めなさい(P324)

2)任意unsigned int型数値のビットパターンを表示(P328)