副作用が発生する式の評価順序に依存しないようにすること

解説

1, 2のようなコードの動作は未定義であり、 func1から実行されるのかfunc2から実行されるかは処理系依存。 必ず3のような書き方を行い、func1, func2が実行される順番を明示的に指定すること。

#include <stdio.h> 

int G_a;
int x, y, z;

int main(void){
    /* 1. 非適合例 */
    G_a = 11;
    x = func1() + func2();  //func1から実行されるとは限らない
                            //func1から実行されたのはたまたま
    printf("x: %d\n", x);  
    
    /* 2. 非適合例 */
    G_a = 11;
    y = func2() + func1();  //func2から実行されるとは限らない
                            //func2から実行されたのはたまたま
    printf("y: %d\n", y);   
    
    /* 3. 適合例 */
    G_a = 11;
    z = func1();            //確実にfunc1から実行される
    z += func2();
    printf("z: %d\n", z);
    
    return 0;
}

int func1(void) {
    G_a = G_a / 2;
    return G_a;
}

int func2(void) {
    G_a = G_a * 2;
    return G_a;
}

出力

x: 15
y: 33
z: 15

extern宣言した配列のサイズをsizeofで取得するには

正しく配列のサイズを取得できるケース

test.c

int array[] = {1,2,3};

Main.c

#include <stdio.h> 

extern int array[3];
int array2[] = {1,2,3};



int main(void){
    printf("array size is %d\n",(int)sizeof(array));
    printf("array2 size is %d\n",(int)sizeof(array2));
    
    return 0;
}

出力

array size is 12
array2 size is 12

正しく配列のサイズを取得できないケース

test.c

int array[] = {1,2,3};

Main.c

#include <stdio.h> 

extern int array[];
int array2[] = {1,2,3};



int main(void){
    printf("array size is %d\n",(int)sizeof(array));
    printf("array2 size is %d\n",(int)sizeof(array2));
    
    return 0;
}

出力

Main.c:9:44: error: invalid application of 'sizeof' to an incomplete type 'int []'
    printf("array size is %d\n",(int)sizeof(array));
                                           ^~~~~~~
1 error generated.

なぜ正しく配列のサイズが取得でいないのか

素数を指定していないextern宣言した配列は不完全型であるため、 arrayにはsizeofを使うことができない。

不完全型とはなにか?

C言語の方は、大きく次の3つに分かれる。

  • 関数型
  • オブジェクト型
  • 不完全型

不完全型には次のようなものがあります。

  • メンバーがまだ指定されていない構造体型
  • メンバーがまだ指定されていない共用体型
  • 次元がまだ指定されていない配列型

今回は「次元がまだ指定されていない配列型」に該当するため、 配列のサイズを取得することができませんでした。

ちなみに、arrayのサイズはMain.cのコンパイル時に決定されるのですが。 不完全型のサイズは決定することができないため、コンパイルエラーとなりました。

回避方法

extern宣言の配列の要素数に正しい値を入れる

test.h

#define ARRAY_SIZE 3

test.c

#include "test.h"

int array[ARRAY_SIZE] = {1,2,3};

Main.c

#include <stdio.h> 
#include "test.h"

extern int array[ARRAY_SIZE];
int array2[] = {1,2,3};


int main(void){
    printf("array size is %d\n",(int)sizeof(array));
    printf("array2 size is %d\n",(int)sizeof(array2));
    
    return 0;
}

出力

array size is 12
array2 size is 12

Eclipse に C/C++ 開発ツール (CDT) を導入

Eclipseとは

Eclipseは、IBMによって開発された統合開発環境 の一つです。 統合開発環境が何かというと、ソフトウェアの開発において用いられるエディタ、コンパイラ、リンカ、デバッガ、その他の支援ツールなどを統合・統一化した開発環境のことです。 統合開発環境のことをIDE(Integrated Development Environment)とも言いますね。

Eclipse CDTってなに?

Eclipseのパッケージのひとつであり、 Eclipseのプラットフォームに基づいた、C, C++で開発するための統合開発環境を提供します。

パッケージというのは、 開発に必要なプラグインを組み合わせてセットにしたものです。 Eclipse CDT以外には、下記のようなパッケージが存在します。

  • Eclipse IDE for Java EE Developers Java EE および Webアプリケーション を開発するための構成
  • Eclipse for PHP Developers PHP開発を行うための構成
  • Eclipse IDE for Automotive Software Developers 組み込み車載ソフトの開発に使われる Framework と ツール を含む構成。

どのバージョンのEclipseがいいの?

Eclipseには様々なバージョンがあります。 執筆時点では、Eclipse Photon (4.8)が最新のようです。 新しいバージョンのEclipseは私のPCでは重いため、少し古いバージョンである Eclipse Indigoを使用しています。

ちなみに私のPCのスペックは下記です。

メーカ:Panasonic 型番:CF-NX2 CPU:Intel Core i5-3340M メモリ:8GB SSD:256GB

Eclipse Indigoでも問題なく使用できていますが、 追加するプラグインによっては古いバージョンをサポートしていない可能性があります。

PCのスペックに余裕のあるかたは、最新のバージョンを入れてください。

Eclipseのダウンロード

Eclipse Indigo SR2 Packagesをダウンロードします。

www.eclipse.org

Eclipseのインストール

ダウンロードした eclipse-cpp-indigo-SR2-incubation-win32-x86_64.zip を解凍してください。 Eclipseインストーラは付属せず、インストールは不要です。 実行ファイルを直接実行します f:id:a-hayashi0113:20180926013625p:plain 私の場合は、解凍してできたeclipseフォルダをCドライブ直下に置いています。 C:\eclipse

これでインストール完了です。

プロジェクトの作成方法

C:\eclipse\eclipse.exe を実行してください。

f:id:a-hayashi0113:20180926013625p:plain

ワークスペースの作成場所を設定して、OKをクリックします。 今後、ワークスペースのあるディレクトリで作業を進めていくことになります。

プロジェクトを作成します。 File->New->C Projectを選択します。

f:id:a-hayashi0113:20180926014011p:plain

適当なProject nameを入力し、 Project TypeはHello World ANSI C Projectを選択します Tool chainsにはCygwin GCCを選択します。

Hello World