Menu

Cloud9 ではじめる C言語

今回は、Cloud9でC++環境を作成して、C言語の学習をします。


cloud9の画面

GCCが標準でインストールされてます。

masasikatano:~/workspace $ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04.1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.1) 
masasikatano:~/workspace $ 

今回も、 ドットインストールのC言語入門を見ていきます。

Hello Worldを出力する

まずは、次のようなファイルを直下に作成します。

#include <stdio.h>

int main(void) {
    printf("hello world!\n");
    return 0;
}
masasikatano:~/workspace $ gcc -o hello hello.c
masasikatano:~/workspace $ ll
total 44
drwxrwxr-x  3 ubuntu ubuntu 4096 May 24 02:03 ./
drwxr-xr-x 15 ubuntu ubuntu 4096 May 24 01:53 ../
drwxr-xr-x  3 ubuntu ubuntu 4096 May 24 01:53 .c9/
-rw-rw-r--  1 ubuntu ubuntu   92 May  2 10:50 Makefile
-rw-rw-r--  1 ubuntu ubuntu 1005 May  2 10:50 README.md
-rwxr-xr-x  1 ubuntu ubuntu 8551 May 24 02:03 hello*
-rw-rw-r--  1 ubuntu ubuntu   61 May  2 10:50 hello-c-world.c
-rw-rw-r--  1 ubuntu ubuntu   82 May  2 10:50 hello-cpp-world.cc
-rw-r--r--  1 ubuntu ubuntu  132 May 24 02:03 hello.c
masasikatano:~/workspace $ ./hello
hello world!

C言語の表現に慣れる

データ型、文字列、関数、静的変数など、C言語の仕様に沿ってコーディングします。

#include <stdio.h>

/*
代表的なデータ型

int(整数) 
%d であらわす

float(実数)
%f であらわす

char(文字)
%c であらわす

文字列
%s であらわす

文字列: charの配列(終端は'\0')
char s[] = ('a','p','p','l','e','\0',);
char s[] = "apple";
*/ 

/*
関数の書き方
*/
float getMax(float a, float b){
    
    /* 通常のif文での書き方
    if (a >= b) {
        return a;
    } else {
        return b;
    }
    
    */
    /* 三項演算子での書き方 
       返り値 = (条件) ? A : B */
    return (a >= b) ? a : b;
}

/*
静的変数と普通の変数
静的変数 : プログラムが終了するまで値が保持される変数
*/
void staticValTest(void){
    static int a = 0; /* 静的変数 */
    a++;
    
    int b = 0; /* 普通の変数 */
    b++;
    
    printf("a : %d\n",a);
    printf("b : %d\n",b);
    printf("\n");
}

int main(void) {
    
    int x = 10;
    float y = 5.2;
    float z = 5.3;
    char c = 'A';
    
    printf("関数の使い方\n");
    printf("%f\n",getMax(y,z));
    printf("\n");
    
    printf("標準出力と変換指定文字\n");
    printf("x = %d, y = %f, c = %c\n",x,y,c);
    printf("\n");
    
    printf("静的変数について\n");
    staticValTest();
    staticValTest();
    staticValTest();
    staticValTest();
    staticValTest();
    
    printf("文字列について\n");
    char s[] = "apple";  //文字列は配列で表す
    printf("%c\n",s[1]); // pが表示される
    printf("%s\n",s); // appleが表示される
    
    return 0;
}
masasikatano:~/workspace $ gcc -o hello hello.c
masasikatano:~/workspace $ ./hello 
関数の使い方
5.300000

標準出力と変換指定文字
x = 10, y = 5.200000, c = A

静的変数について
a : 1
b : 1

a : 2
b : 1

a : 3
b : 1

a : 4
b : 1

a : 5
b : 1

文字列について
p
apple

ポインタとアドレス領域

#include <stdio.h>

/*
ポインタ: アドレスを格納するための変数
メモリ(記憶領域)

* : 間接演算子
& : アドレス演算子

*/

int main(void) {
    int i;
    i = 10;
    
    int* pa; //int型のポインタという意味で「int*」
             //paが変数名
    
    pa = &i; //&iで、iが入っているアドレスを、paへ代入
    
    printf("%d\n",*pa); //間接演算子「*」を利用してpaが指し示すアドレスの値を参照する
    
    return 0;
}
masasikatano:~/workspace $ gcc -o pointer pointer.c                                       
masasikatano:~/workspace $ ./pointer
10

ポインタでアドレス領域を節約

ポインタをうまく活用することでアドレス領域を節約することができます。
2種類のファイルを作ります。

#include <stdio.h>

/*
ポインタでアドレス領域を節約(前)
全部で 16アドレス を使用
*/

void f(long i){
    i += 100;
    printf("%ld\n",i);
}

int main(void) {
    long i = 1000;
    f(i);

    return 0;
}

↑ 合計で 16アドレス を使用しています。

#include <stdio.h>

/*
ポイン���でアドレス領域を節約(後)
全部で 8アドレス を使用
*/

void f(long *pa){ // 間接演算子「*」を使用して引数を参照する
    printf("%ld\n", *pa + 100);
}

int main(void) {
    long i = 1000;
    f(&i); // アドレス演算子&を使用して変数iのアドレスを引数として関数fを実行
   
    return 0;
}

↑ こちらはたった 8アドレス でOKです。

値渡しと参照渡し

#include <stdio.h>

/*
参照渡し
*/

void swap(int *pi, int *pj){
    int tmp = *pi;
    *pi = *pj;
    *pj = tmp;
}

int main(void) {
    
    int i = 1;
    int j = 99;
    
    /* swap(i,j);   変数iとjを入れ替える処理をしたい。
                    値渡しでは、返り値一つしか受け取れないので
                    そのままでは実装できない */
                    
    swap(&i,&j); /* そんな時は、参照渡しをして、
                    アドレス値をいれかえる処理で実装できる。*/
    
    printf("i:%d, j:%d\n", i, j);    
    
    return 0;
}
masasikatano:~/workspace $ gcc -o reference reference.c                                     
masasikatano:~/workspace $ ./reference 
i:99, j:1

入れ替わりました。


用語解説

FSF

FSFとは、利用者が自由に改変、再配布などを行うことができるフリーソフトウェアの普及を推進する非営利団体。
1985年にリチャード・ストールマン(Richard M. Stallman)氏を中心とするグループによりMIT(マサチューセッツ工科大学)を拠点に設立された。

FSFの主な活動としては、「GNUプロジェクト」と総称される、主にUNIX系OSで使われるフリーのソフトウェア開発ツールなどの開発、配布や、フリーソフトウェアの使用許諾契約(ライセンス)を定義するGPL(GNU Public License)やLGPL(Lesser GPL)などの策定、普及などがある。

GNU

GNUとは、FSFが進めているUNIX互換ソフトウェア群の開発プロジェクトの総称。   フリーソフトウェアの理念に従った修正・再配布自由なUNIX互換システムの構築を目的としている。   GNUで開発されたソフトウェアに適用されているGPLは、「あらゆるソフトウェアは自由に利用できるべき」というFSFの理念を体現したライセンスとして知られている。

UNIX

UNIXとは、1969年にAT&T社ベル研究所で開発が始まったオペレーティングシステム(OS)。また、その流れを汲むOSの総称。

UNIXは当初から、異なる機種間の移植性や、複数のプログラムを並行して動作させられるマルチタスク、複数の利用者が一つのシステムを利用できるマルチユーザなどの特徴を重視して開発されてきた。初期のUNIXの移植性と開発効率を高めるために考案されたプログラミング言語のC言語はUNIXと共に普及・発展し、様々なソフトウェアの開発に用いられ、多くの派生言語を生み出した。

UNIX系OS

UNIX系OSとは、1969年にAT&T社のベル研究所(Bell Laboratories)が開発した「UNIX」というOSに似た仕様や操作感を持つOSの総称。「UNIXクローン」などとも呼ばれる。

近年ではフリーなUNIX、特にLinuxが目覚しい発展・普及を遂げて注目を集めている。大手メーカーも自社OSのサポートと並行して自社コンピュータをLinuxなどに対応させたり、システム構築に採用したり、社員を開発に参加させたりしている。

UNIX系の系譜

コンパイラ

コンパイラとは、人間に分かりやすく複雑な機能や構文を持つ高水準プログラミング言語(高級言語)で書かれたコンピュータプログラムを、コンピュータが解釈・実行できる形式に一括して変換するソフトウェア。

GCC

gccとは、GNUプロジェクトが開発・公開しているコンパイラ。様々なプログラミング言語のコンパイラを集めたパッケージとなっている。多くのUNIX系OSで標準的に利用され、オープンソースのOSではOS自体のコンパイルに用いられることも多い。

様々な言語に対応しており、標準ではC言語やC++、Objective-C、Fortran、Java、Ada、Goのコンパイラが同梱されている。「gcc」はgcc内のCコンパイラの名称および実行ファイル名でもあり、C++コンパイラのことは「g++」、Javaコンパイラは「GCJ」(GNU Compiler for Java)と呼ばれる。

gccは字句解析などを行うフロントエンド、コードの最適化を行うオプティマイザ、CPU固有のコードを生成するバックエンドに分かれており、フロントエンドやバックエンドを開発・追加することで新しい言語やプロセッサに対応させることができる。標準のフロントエンド以外にもPascalやCOBOLなど様々な言語用のフロントエンドが開発・公開されている。

また、対応するマイクロプロセッサ(MPU/CPU)の種類も豊富で、Intel系プロセッサ(x86、x86-64)のほか、ARMやPowerPC、MIPS、SuperH、PA-RISC、AVRなど様々な命令セットアーキテクチャ(ISA)の機械語プログラムを生成することができる。このため、パソコンなど汎用コンピュータ向けのソフトウェア開発だけでなく、組み込み機器向けや家庭用ゲーム機向けの開発でも利用されることが多い。

gccはGPL(GNU Public License)と呼ばれる利用許諾(ライセンス)に基いてオープンソースソフトウェアとして公開されており、誰でも自由に入手、利用、改変、再配布などをすることができる。

ポインタ

あるオブジェクトがなんらかの論理的位置情報でアクセスできるとき、それを参照するものである。有名な例としてはC/C++でのメモリアドレスを表すポインタが挙げられる。

メモリアドレス

コンピュータにおいてCPUやその他のハードウェアがデータを書き込み、また読み出すメモリ上の位置の一意な識別子である。 典型的には整数として表現される。 現代のバイトアクセスのコンピュータでは、アドレスはメモリ中の1バイトを識別する。

アドレス演算子「&」

プログラミング言語は名前を使って変数への代入やその参照をするように作られています。 C言語ではアドレスを介して変数にアクセスすることもでき,それを実現する手段として2つの演算子( & と * )が用意されています。
「&」 は「アドレス演算子」と呼ばれ、変数が割り当てられているメモリのアドレスを得ることができます。
例えば、変数xが1000番地に割り当てられていたとすると、&xの値は1000になります。
このとき、&xを「変数xへのポインタ」と呼びます。

間接演算子「*」

間接演算子はC言語の初心者の9割はハマルだろう「ポインタ」と深く関係する演算子で、これは「単項演算子」です。ポインタは色々な表現やイメージの仕方があると思いますが、私のイメージは「ダンボール」なんです。

ダンボールの中には数字の値が入っています。
また、ダンボールには中身が分かるようにシールが張ってあり、これが変数名。
一方で、管理人しかわからない通し番号も振ってあり、これがアドレス(番地)。

一つの箱に、「値」「変数名」「通し番号」という3つの属性が付いているわけです。
ある変数名の付いたダンボールには、通し番号であるアドレスが張ってあり、これがポインタ変数。

「このアドレスを頼りにたぐっていって箱を見つけて中身を見る」。これが間接演算子の役目、演算内容です。


覚えていると、いろいろ役に立ちそうです。


参考サイト


Written by masasikatano on Tuesday May 24, 2016

« 良いコードを書く - Laravel5 入門 »


Share