解らないC〜っ!
更新日:2010/6/28


教本や検索エンジンや、先人様方の掲示板で質問してみたりして
種類とか区別とか、自分が解り易い様に、解説とか加えたりしてます。
解説のほとんどは、パクリです。<(_ _)>
このページも、他のムンバさんのページ同様、信用しないで下さい。
相変わらず、いい加減に搭載してますゆえ。(∂∂)♪
サイトや教本、対象レベルによっては
種類や分類などの呼び方や解説などが異なりますので、ご注意下さい。

プログラミングの館に戻る

注釈の無い解説は
ムンバが自分勝手に理解したもので、全く信用できませんが
ほとんどの解説は、他サイト内の内容を引用させて頂いてます。
ので、もし差し障りあれば、ご一報お願い致します。

引用させて頂いた文章に関しては
各所でお断りし、リンクを張らせて頂いています。
詳細は、各サイトの規約を厳守下さい。

・サイト内の一部の転載・引用に関して、許可されてると思われるサイト
 (もしも私の思い違いで不許可でしたら、お手数ですがご一報下さい。)

 苦しんで覚えるC言語

 C言語講座:初級から中級まで

 趣味のプログラミングで楽しく遊ぼう【プログラミングランド】

 JPCERT コーディネーションセンター


・転載・引用に関して、許可が必要なサイト

 初心者のためのポイント学習C言語

 マイコミジャーナルサイト内ハウツー 内「0から始めるC言語」


・転載・引用に関して、許可が必要かどうか自己判断できないサイト
 (不許可でしたら、事後処理となります事ご勘弁下さい。
  お手数ですが、不許可の趣旨、ご一報宜しくお願い致します。)

 ためになるホームページ

 Wikibooks 内の C言語

 柴田望洋後援会オフィシャルホームページ by 言語科学研究所

プログラミングの館
に戻る

記号・アルファベット順 種類や呼び名 する事
#ifndef
#define
#endif
プリプロセッサ命令 条件分岐を行う
#include 前処理指令 ファイルをインクルードする
& ビット(論理)積演算子 ビット積
bool 真偽値型(マクロ)
break 制御文
char データ型
const 修飾子
delete 演算子(C++のみ)
extern 外部変数
float データ型 浮動小数型宣言
for 制御文
free 記憶域管理関数
gets_s 関数
if 制御文
int データ型 整数型宣言
INT_MAX 定数 int型の最大値を表す
main 関数
malloc 関数
memcpy 文字列複写関数
memcpy_s 文字列複写関数
new 演算子(C++のみ)
NULL 定数(ヌルポインタ)
printf 関数
rand 関数
return 制御文
sizeof 演算子
sprintf 関数
sprintf_s 関数
srand 関数
static 静的変数
strcat 関数
strcmp 関数 2つの文字列を比較する
strcpy 関数 文字列を連結
strcpy_s 関数
strlen 関数
strncat_s 関数
struct 構造体
time 関数
unsigned 修飾子
void データ型
while 制御文


あいうえお順 種類や呼び名や意味
ローカル変数
グローバル変数
変数
配列 同じ型のデータの集合
ポインタ 変数のアドレスを記憶する変数

プログラミングの館に戻る


#ifndef
#define
#endif
(条件分岐を行う)
プリプロセッサ命令

#ifndef は、条件岐を行うプリプロセッサ命令(コンパイラの処理を変える命令。)
ndef は Not Define の略で「定義されていない」事を意味する。
「#ifndef ○○」は「○○というキーワードが定義されていなければ
#endif までの範囲の記述を有効にする」という意味になる。
逆に○○が定義されていれば#endif までの範囲の記述はコンパイラから無視される。

==================================================================
以下 趣味のプログラミングで楽しく遊ぼう【プログラミングランド】内より引用

#ifdef コマンドは、#define で定義された識別子が

あるかどうかをチェックするコマンドです。

あとの処理は、#if と同じく、条件付きコンパイル機能となります。

#ifdef コマンドの逆の意味である #ifndef コマンドも存在します。

こちらの意味は、#define 識別子が定義されてなかったら・・・。となります。

構文

#ifdef #define識別子
   何らかの処理
#elif 条件
   何らかの処理
#else
   何らかの処理
#endif


条件に合った部分の処理だけをコンパイル対象とします。

サンプルプログラムです。

#include <stdio.h>

#define SW // 定義を外す時は、この1行をコメントアウトする。

void main(void) {
#ifdef SW
   printf("SW定義ありプログラム");
#else
   printf("SW定義なしプログラム");
#endif

}



#ifdef#ifndef コマンドは、別の表現方法もあります。

#if defined#if !defined です。

それぞれ、同じ意味を表します。

#if defined コマンドの省略形が、#ifdef

#if !defined コマンドの省略形が、#ifndef

となっています。

以上 趣味のプログラミングで楽しく遊ぼう【プログラミングランド】内より引用
==================================================================

#include 前処理指令
     
ファイルをインクルードする(取り込む)

仕様:ヘッダ名を<>で囲んだ場合は「ヘッダ」を取り込む。
    (ヘッダはファイルとは限らない。)
    #include <stdio.h> #include <string.h> など

    ""で囲んだ場合は、ソースファイルを取り込む。
    #include "DxLib.h" #include "header.h" など

    ""で囲まれた場合は、処理系の検索順序に従ってファイルを探し
    見つからない場合は、 <>で囲んだ場合の検索順序で探す。

用法:#include指令を記述した場所にソースが取り込まれるので
    これを利用して、そのときどきの状態を変化させることができる。
    具体的には<assert.h>を調べる。
    また、実装の一部を別のソースファイルに分離することもできる。

& ビット積演算子・論理積演算子など

ビット単位で比較してともに 1 なら 1 。
どちらかが 0 なら 0 。

short型を2バイトとすると
 0000 0000 0000 0001 (10進法: 1 )
 0000 0000 0000 0011 (10進法: 3 )

ビット積

  0000 0000 0000 0001
 &0000 0000 0000 0011

(工事中)

bool 真偽値型(マクロ) C++では基本型のうちの汎整数型<by たかぎさん

真(True)と偽(False)の二つの値しか持たない。

真偽値を使いたい時で、かつC99以上に対応したコンパイラが使える場合で使う。
また、C90やC95への移植性に配慮する場合は使うべきでは無い。<by 高木さん

ON・OFF、OK・NG、成功・失敗など二者択一の場合に使うのが一般的かと思われる。
戻り値が1か0しかありえない関数なんかだと、bool型にしてしまった方が分かりやすいかもしれない。
ただ、bool型でなければいけない状況というのは思い付かないです。<by バグさん

break 制御文

for・while・switch文などの文中から抜けたい時に使う(制御)文。

char データ型

変数の型を宣言する。
文字を記憶する型。

const 修飾子

指定した変数が定数であることを指定する。
変数の宣言に const をつけることでその変数の値が書き換えられない様にする。

delete 演算子(C++のみ) #include <iostream>

=================================
以下 Programing Place内より引用

○newとdelete

C言語編で動的なメモリ確保について説明しました。そのとき使ったのが、malloc関数とfree関数でした(第55章参照)。C++でも、もちろんこれらの関数を使用して動的なメモリ確保が行えますが、通常は使いません。代わりに使われるのが、この章で紹介する new演算子delete演算子です。

new演算子を使うとメモリの動的確保が行え、delete演算子によって解放することができます。ここで注意してほしいのですが、newとdeleteは演算子です。mallocやfreeは関数です。この違いには重要な意味があるのですが、現段階では知る必要はありません(第17章で演算子のオーバーロードについて説明しますが、これと関係します)。

○newとdeleteを使う

まずは単純にint型1つ分の領域を動的確保してみます。

#include <iostream>

int main()
{
        int *p;
        
        p = new int();  // int型の領域を動的確保
        *p = 123;
        std::cout << *p << std::endl;
        
        delete p;       // 動的に確保した領域を解放
        
        return 0;
}

new演算子は、その直後に書いた型の領域を確保します。上の例ならint型になります。intの直後に付いている括弧には、コンストラクタに渡す引数を指定できます。new演算子は、メモリの確保と共に、コンストラクタを呼び出します。実はC++では、int型のような基本データ型にもコンストラクタがあります。試しに、( )の中に123と書き、直後の *p = 123; をコメントアウトして試してみると、確かに123と出力されます。よってC++では、次のどの方法を使っても、初期化処理が行えます。

int num = 100;
int num(100);
p = new int(100);

もちろん3つ目の方法では、pがポインタですし、使い終わったらにdeleteを呼ぶ必要があります。ついでに話しておくと、C++では「代入」と「初期化」は異なります。コンストラクタが呼び出されるのは「初期化」のときです。

delete演算子の使い方は、newで確保した領域を指すポインタを、deleteの直後に記述するだけです。newで確保した領域でないと解放は行えません(malloc関数で確保した領域をdeleteで解放してはいけない)。なお、NULL で初期化されているポインタをdelete演算子に指定すると、何も起こらないことが保証されています。

new演算子がコンストラクタを呼び出しているのと同じで、delete演算子はデストラクタを呼び出します。

○配列を使う

次にnew演算子を使って、配列用の領域を確保してみます。

#include <iostream>

int main()
{
        int *p;
        int i;
        
        p = new int[10];  // int型10個分の領域を動的確保
        for(i=0; i<10; ++i)
        {
                p[i] = i;
                std::cout << p[i] << std::endl;
        }
        
        delete [] p;       // 動的に確保した領域を解放
        
        return 0;
}

new演算子を使って配列を確保するには、型指定の直後に[]を使って、配列に含まれる要素数を指定します。上の例を見て分かるように、配列を動的確保する場合に()はありません。つまり、コンストラクタに引数を渡せません。配列を動的確保する場合、コンストラクタは呼び出されないのではなく、引数がないデフォルトのコンストラクタが呼び出されています。このように、呼び出すコンストラクタを指定しなかった(できなかった)場合に、呼び出される、引数のないコンストラクタをデフォルトコンストラクタといいます。あるクラスに関して、1つも明示的にコンストラクタを宣言していない場合、コンパイラが自動的にデフォルトコンストラクタ生成します。1つでもコンストラクタを宣言している場合には、このような自動的な生成は行われません。

重要なのはdelete演算子の使い方です。new演算子を使って配列を確保した場合、delete演算子にも[]を付けなければなりません。これを付けないと、正しく解放できません(恐らく、配列の先頭の要素についてだけ解放されるが、それすらも保証されている訳ではない)。この[]の付け忘れは非常によくある間違いです。コンパイルは普通に成功してしまうので気をつけて下さい。

○newでインスタンス化

もちろん、new演算子を使ってクラスをインスタンス化できます。

#include <iostream>

int main()
{
	CSample* p;
	
	p = new CSample( 100 );
	std::cout << p->Get() << std::endl;
	delete p;
	
	return 0;
}

使い方は全く同じです。当然、コンストラクタを呼び出せます(クラスを配列としてインスタンス化する場合は除く)。 new演算子を使ってインスタンス化する場合、そのメンバ変数やメンバ関数をアクセスするときに、アロー演算子を使うことになります。まあポインタ経由のアクセスになるので、当然といえば当然です。

delete演算子についても特殊なことはありません。ここでも[ ]を付けるか付けないかには注意が必要です。

○malloc関数を使わない理由

C++では通常、malloc関数(callocやreallocも含む)を使いません。その理由は簡単で、malloc関数ではコンストラクタが呼び出せないからです。デフォルトコンストラクタも呼び出されません。同様に、free関数ではデストラクタが呼び出されません

以上 Programing Place内より引用
=================================
extern 外部変数

extern 変数は、関数の外側で宣言し、他のソースファイルからも参照できる様にする。
複数ソースコードをまたいで、変数やメソッドを使用するときに時に使う。

================================
以下 Programing Place内より引用

extern指定子を付けると
「宣言が他の場所にも書かれている」ことをコンパイラに知らせる
ことができます。
コンパイラはexternが付いていることを発見すると
他の場所で同様の名前で宣言されている変数を見つけてもエラーを出しません。
なお、定義はプログラム中で1箇所だけしか許されないので
ソースファイルの側に記述
しておきます。
このとき、そのソースファイルが、宣言の記述されているヘッダファイルを
インクルードしている必要があります(正確には、宣言が見える位置に定義を書かなければならない)。
なお、extern指定子は、関数プロトタイプに付けることもできますが
関数に関しては付けなくても問題はありません。
(元々定義はソースファイル側の1箇所にしかないはずだから)。

以上 Programing Place内より引用
================================


float データ型

変数の型を宣言する。
浮動小数点を記憶する型。
コンパイラによって異なるが、32ビットである事が多い。

for 制御文

for (初期条件; 終了条件; カウンタの増減など){ ;}


free 記憶域管理関数 #include <stdlib.h>

======================================
以下 c言語プログラムの基本形より引用

記憶域管理関数
free
ヘッダ #include <stdlib.h>
形 式 void free(void *ptr);
機 能 free関数、ptrが指す領域を解放し、その後の割付けに使用できるようにする。ptrが空ポインタの場合、何も動作しない。それ以外の場合、実引数がcalloc関数、malloc関数もしくはrealloc関数によって以前に返されたポインタと一致しないとき、またはその領域がfreeもしくはreallocの呼出しによって解放されているとき、その動作は未定義である。
返却値 free関数は、値を返さない。

以上 c言語プログラムの基本形より引用
======================================

gets_s 関数 #include <stdio.h>

Visual C++ では、gets関数よりも、gets_s関数の使用が推奨されている。
gets_s関数は、2つ目の引数にchar型配列のサイズを指定するので
バッファオーバーフローの発生を検出できる。

char *gets_s(char *buffer, size_t sizeInCharacters);
size_t型は、マイクロソフトが定義した型で、実態はunsigned int 。

================================
以下 MSDNライブラリ 内より引用

gets_s 関数は、stdin 標準入力ストリームから行を読み取り、buffer に格納します。
行は最初の改行文字 (\n) までのすべての文字で構成されています。
その後、gets_s は、改行文字を null 文字 (\0) に置換してから行を返します。
これとは対照的に、fgets_s 関数は改行文字を保持します。

最初に読み取られた文字がファイルの終端の文字である場合
null 文字が buffer の先頭に格納され、NULL が返されます。

ワイド文字を扱う場合は、gets_s ではなく _getws を使用します。
引数にはワイド文字列を指定します。また戻り値もワイド文字列です。

bufferNULL の場合、sizeInCharacters が 0 以下の場合
またはバッファが小さすぎて入力行と終端の null を格納できない場合
これらの関数は「パラメータの検証」(←NCDMライブラリ 内より引用)に説明されているように
無効なパラメータ ハンドラを呼び出します。実行の継続が許可された場合
これらの関数は NULL を返し、errno を EINVAL に設定します。

C++ では、これらの関数の使用はテンプレートのオーバーロードによって簡素化されます。
オーバーロードでは
バッファ長を自動的に推論できる (サイズの引数を指定する必要がなくなる) だけでなく
古くてセキュリティが万全ではない関数を新しく安全な関数に自動的に置き換えることができます。

以上 MSDNライブラリ 内より引用
=================================


if 制御文

if (条件式が真){ 実行;}


int データ型

変数の型を宣言する。
整数を記憶する型。
コンパイラによって異なるが、32ビットである事が多い。

INT_MAX 定数 #include <limits.h>

int型の最大値(≧32767)を表す。

/* try001.c */

#include <stdio.h>
#include <limits.h>

int main()
{
        printf( "%d\n", INT_MAX );
        
        return 0;
}

実行結果: 2147483647


(以下、14歳からはじめる C言語オンラインゲーム プログラミング教室より引用)

g_lastcalltime = GetNowCount() & INT_MAX;

このサンプルソースでは、DXライブラリの GetNowCount関数の結果を、正の数にするため

GetNowCount() & INT_MAX;

と言う計算を行っている。

Windows内部では、起動後の経過時間を、正負の符号無しの unsigned int で管理してる。
ところが、GetNowCount関数は、これを符号付の int に変換して返すため
符号付き整数では最上位ビットが、「0の時に正の数、1の時に負の数」とするため
符号付きから符号無し整数に変換すると、正の数が負になる事がある。
例えば、符号無し整数の
2,147,483,648 を符号付きの int に変換すると、-2,147,483,648 となる。
そこで、ビット演算子の & を使って、最上位ビットを 0 に変え、つねに正になる様にしている。

なお、正の最大値を表す定数 INT_MAX
C標準ライブラリの limits.h で定義されている。


(以下、ウィキペディアより引用)

整数型の大きさ <limits.h>

整数型の大きさを表すマクロの定義。

  • CHAR_BIT - char 型を構成するビット数(≧8)
  • MB_LEN_MAX - 処理系がサポートするマルチバイト文字の最大バイト数
  • CHAR_MAX - char 型の最大値。 SCHAR_MAX または UCHAR_MAX と同じ
  • CHAR_MIN - char 型の最小値。 SCHAR_MIN または 0 と同じ
  • SCHAR_MAX - signed char 型の最大値(≧127)
  • SCHAR_MIN - signed char 型の最小値(≦-127)
  • UCHAR_MAX - unsigned char 型の最大値(≧255)
  • SHRT_MAX - short 型の最大値(≧32767)
  • SHRT_MIN - short 型の最小値(≦-32767)
  • USHRT_MAX - unsigned short 型の最大値(≧65535)
  • INT_MAX - int 型の最大値(≧32767)
  • INT_MIN - int 型の最小値(≦-32767)
  • UINT_MAX - unsigned int 型の最大値(≧65535)
  • LONG_MAX - long 型の最大値(≧2147483647)
  • LONG_MIN - long 型の最小値(≦-2147483647)
  • ULONG_MAX - unsigned long 型の最大値(≧4294967295)

main 関数

プログラムの実行開始部分(メインルーチン)。
プログラムは、main関数が1番始めに動作する。
プログラムは、mainという予約された名前の関数から実行される。

malloc 関数 #include <stdlib.h>

================================
以下 C言語 標準関数内より引用

書式

#include <stdlib.h>

void * malloc( size_t len );

■戻り値:
lenで指定された大きさの領域を確保してその先頭アドレスを返す。エラー時はNULL(\0)を返す。

関連関数
説明

lenで指定された大きさの領域を確保してその先頭アドレスを返す。確保した領域の内容は不定である。エラー時はNULLを返す。

確保した領域はfreeで開放しなければならないが、プログラム終了時であればOSが自動で開放する。

サンプル
(元のソースを、少しいじってます。)
実行結果

ptr=テストデータ

以上 C言語 標準関数内より引用


memcpy 文字列複写関数 #include <string.h> 

=================================
以下 Programing Place内より引用

memcpy()は、メモリ上の指定した位置にあるデータを、他の位置にコピーする 関数。

void* memcpy(void* s1, const void* s2, size_t n);

第1引数がコピー先領域の先頭アドレス、第2引数がコピー元領域の先頭アドレスです。
第3引数には、コピーするデータの大きさをバイト単位で指定します。
戻り値には、第1引数で指定したアドレスがそのまま返されます。

memset()のところで触れたように、メモリ操作系の関数は、文字列操作関数と似ています。
memcpy()の文字列専用バージョンがstrcpy()ということになります。
memcpy()の方が、引数が1つ増えていて、そこにデータの大きさを指定するようになっています。
これは、文字列の場合なら、末尾に'\0'があることを前提としているため
データの大きさを指定しなくても、自動的に末尾を判定できるためです。
memcpy()は、どんな種類のデータにでも対応できる反面
データサイズを具体的に指定する必要があります。
memcpy()は、データサイズを指定するため
何らかの理由で末尾に'\0'のない文字列のコピーにも利用できることを忘れないで下さい。
文字列のコピーには
必ずしも strcpy()を使わなければならないということはありません。

ここでは、文字列の途中に'\0'が登場していても
memcpy()ならコピー可能であることを確かめてみましょう。

#include <stdio.h>
#include <string.h>

int main(void)
{
        char str[12] = "abcde\0fghij";  /* 途中に\0がある */
        char out[12];
        int i;
        
        memcpy( out, str, 12 );  

        /* strからoutへコピー *//* 結果を出力 */
        for( i = 0; i < 12; ++i )
        {
                printf( "%c", out[i] );
        }
        
        return 0;
}

出力される結果は、

abcde fghij

となります。'\0'はヌル文字なので、出力するとその部分が空白になっていることが分かります。
そして、それより後ろにあるfghijも正しく出力できています。

さて、もう1つプログラム例を見て下さい。

#include <stdio.h>
#include <string.h>

int main(void)
{
        char str[6] = "abcde";
        int i;
        
        memcpy( &str[2], str, 3 );  

        /* "abc"の部分を"cde"の部分にコピー? *//* 結果を出力 */
        for( i = 0; i < 6; ++i )
        {
                printf( "%c", str[i] );
        }
        printf( "\n" );
        
        return 0;
}

今回のコピー元は配列strの先頭、コピー先は同じ配列の3文字目の部分になっています。
そして、コピーする大きさは3バイトです。
元の配列には"abcde"が格納されているので、この実行結果は

ababc

となることを期待するでしょう。しかし、実行結果は次のようになる場合もあります。

ababa

memcpy()の重要な注意点がこれです。
つまり、コピー元の範囲と、コピー先の範囲との一部が重なっている場合には
memcpy()は正しく動作しないかも知れません

今回の場合、str[2]の部分が重なってしまっているので、このようなことが起こります。
もし、領域が重なってしまっている場合には、memcpy()ではなくmemmove()を使います

先ほどから「場合もあります」とか「かも知れません」と書いていますが
これはコンパイラの実装による部分なので、どうなるかは分かりません。
例えば、VisualC++2005やVisualC++.NET2003で確認すると
上のプログラムは期待した通り"ababc"と出力します。
Borland C++ Compliler5.5.1で確認すると、"ababa"を出力しました。

以上 Programing Place内より引用
=================================


memcpy_s 文字列複写関数(C++) #include <string.h>

================================
以下 MSDNライブラリ 内より引用
errno_t memcpy_s( void *dest, size_t numberOfElements, const void *src, size_t count );

パラメータ

dest:コピー先のバッファ。
numberOfElements:コピー先のバッファのサイズ。
src:コピー元のバッファ。
count:コピーする文字数。
戻り値:正常終了した場合は 0 を返します。失敗した場合はエラー コードを返します。

memcpy_s は、count に指定したバイト数を src から dest にコピーします。
コピー元とコピー先を同じにした場合の memcpy_s の動作は未定義です。
重なり合う領域を処理するには、memmove_s を使用します。

これらの関数では、パラメータの検証が行われます。
dest
または src が null ポインタであるか
numberOfElements がバッファに対して小さすぎる場合
パラメータの検証」に説明されているように
これらの関数では無効なパラメータ ハンドラが呼び出されます。
実行の継続が許可された場合、これらの関数は EINVAL を返し、errnoEINVAL に設定します。

以上 MSDNライブラリ 内より引用
=================================


new 演算子(C++のみ) #include <iostream>

=======================================
以下 ためになるホームページ 内より引用

new演算子
C++には、動的確保の演算子としてnew演算子が用意されている。
new演算子は、動的確保とコンストラクタの呼び出し(初期化)を行う。
Cの関数mallocは動的確保ができるが、コンストラクタの呼び出しは行われない。
newとmallocの例
#include <iostream>
using namespace std;

class CTest {
public:
  CTest() {
    cout << "Constructor " << endl;
  }
};
int 
main(int argc, char* argv[]) {

  CTest *test1 = new CTest();
  CTest *test2 = (CTest*)malloc(sizeof(CTest));
  delete test1;
  free(test2);
  return(0);
}

上記の例を実行すると"Constructor"は、一回しか呼ばれない事がわかる。

(書式) new type;
int型などの場合は、動的確保する時に、初期化をする事もできる。
(書式) new type(初期化値);
newの例
#include <iostream>
using namespace std;

int 
main(int argc, char* argv[]) {

  /// 動的確保を行う
  int *test1 = new int;
  
  /// 動的確保をし、1に初期化する
  int *test2 = new int(1);
  
  cout << *test2 << endl;
  
  delete test1;
  delete test2;
  return(0);
}


配列の確保
配列を確保するには、以下の書式を使う。
(書式) new type[size];
newで配列確保の例
#include <iostream>
using namespace std;

int 
main(int argc, char* argv[]) {

  /// int型10個を動的確保
  int *test1 = new int[10];
  
  int i;
  for ( i = 0; i < 10; i++) {
    test1[i] = i;
  }
  
  delete[] i;

  return(0);
}

newを使ってコンストラクタをもう一度呼び出す
new演算子を使って、コンストラクタをもう一度呼び出す事ができる。
(書式) new (void*)address type;

new使い方の例
#include <iostream>
using namespace std;

class CTest{
public:
  CTest() : m_a(0) {
    cout << "Default Constructor : m_a = " << m_a << endl; 
  }

  CTest(int a) : m_a(a) {
    cout << "OverLoad Constructor : m_a = " << m_a << endl;
  }
  int getParam(void){
    return(m_a);
  }
private:
  int m_a;
};

int 
main(int argc, char* argv[]) {
  CTest *p = new CTest();
  
  /// 同じオブジェクトに対して、引数ありのコンストラクタを呼び出す
  CTest *q = new ((void*)p) CTest(3);

  cout << "pointer p->m_a" << p->getParam() << endl;
  cout << "pointer q->m_a" << q->getParam() << endl;
  delete p;
  return(0);
}


以上 ためになるホームページ 内より引用
========================================

NULL 定数(ヌルポインタ)

==============================================
以下 予定は未定 内の NULLについて より引用

NULLとは

NULLとはC++のプログラミング上でさまざまな意味を持たされています。

しかしJavaのnullとは違い、 C++のNULLはC++のキーワードではなく単なるマクロ定義です。

NULLの欠点

NULLはマクロ定義なので、処理系によって定義がばらばらです。
よってNULLの意味は他の実装系では違う意味になり、
思ったとおりの動作をしない可能性があります。

NULLの代用

そもそもNULLはC言語との互換性のために残されているマクロ定義であり
C++では不必要な存在なのです。

C++で(C言語で言う)NULLを表現したい場合、 0を使用します。
0は任意の型のヌルポインタに変換される事が保証されているので、
どんなNULLマクロよりも安全です。

0の問題

0を使用する方法にもひとつだけ欠点があります。

それは、0は任意の型のヌルポインタに変換できますが、 整数型でもあります。
なので、クラス型を引数にもち
ヌルポインタも引数として許す関数と 整数型を引数に取る関数を同時に定義すると
ヌルを渡した際に常に整数型を引数に取る関数が呼び出されることになります。

これはC++自体の欠陥のひとつでしょう。
これを解決するのは面倒で複雑な方法を使用しないといけないので
このような関数の多重定義は行わないようにしましょう。

先端技術応用null

ここで紹介するのはこれまで挙げた欠点が全くない、先端技術応用nullです。

これはEffective C++に掲載されている手法です。

const class {
public:
    template<class T>
    operator T*() const { return 0; }
    // あらゆる型のメンバポインタへの変換
    template<class C, class T>
    operator T C::*() const  { return 0; }
private:
    void operator&() const;
} null; 

この先端技術応用nullには1つだけ欠点が存在します。

それは、このnullが使ってもらえるかどうかわからないことです。

今までどおりのNULLの定義や、推奨されている0の使用を防ぐことは出来ません。

用語的には "ヌルポインタ" と呼ばれる。。
'\0'は "ヌル文字" と呼ばれる。

以上 予定は未定 内の NULLについて より引用
==============================================

C言語では、NULLはメモリの0番地。
 と、今の所、理解した。

printf 関数 #include <stdio.h>

整数: %d
文字: %c
文字列: %s
浮動小数: %f

・整数の表示例


・文字の表示例


・文字列の表示例


・ポインタを使った文字列の表示例


・浮動小数の表示例

実行結果 12.456000

・浮動小数の桁数の表示例

実行結果 12.4560

%7.4 ( . )を含む全桁数表示7桁 小数点以下の桁数表示4桁

これを %8.2 に変更した実行結果

(行頭から3桁分のスペースが空いて)12.46
の8桁が表示される。
==================================
以下 C言語 - Wikibooks 内より引用

変換指定は次の形式をとる。([ ]内は省略可能)

%[フラグ][最小フィールド幅][.精度][長さ修飾子]変換指定子

フラグ

変換指定のフラグは以下の通り。

フラグ 意味
- フィールドの左寄せ
+ 常に符号を出力
空白 数値が正または 0 の場合は符号の代わりに空白を出力
# 代替形式。基数を表すプレフィックスの出力等
0 出力文字数が最小フィールド幅未満の場合は'0'を出力

長さ修飾子

修飾子 意味 導入バージョン
hh 実引数は char 型 C99以降
h 実引数は short 型 全バージョン
l(エル) 実引数は long 型または wchar_t 型 wchar_t についてはC95以降
ll(エルエル) 実引数は long long 型 C99以降
j 実引数は intmax_t 型 C99以降
z 実引数は size_t 型 C99以降
t 実引数は ptrdiff_t 型 C99以降
L 実引数は long double 型 全バージョン

変換指定子

指定子 意味 導入バージョン
d, i 10進符号付き整数 全バージョン
u 10進符号無し整数 全バージョン
o 8進符号無し整数 全バージョン
x, X 16進符号無し整数( X は大文字で出力) 全バージョン
e, E 指数形式浮動小数点数( E は大文字で出力) 全バージョン
f, F 小数形式浮動小数点数( F は大文字で出力) 全バージョン
g, G e または f 形式のうち適した方( G は大文字で出力) 全バージョン
a, A 16進浮動小数点( A は大文字で出力) C99以降
c 文字 全バージョン
s 文字列 全バージョン
p ポインタの値 全バージョン
n 整数変数に出力済み文字数を格納 全バージョン
% '%'の出力 全バージョン

以上 C言語 - Wikibooks 内より引用
==================================


rand 関数 #include <stdlib.h>

===================================================================
以下 趣味のプログラミングで楽しく遊ぼう【プログラミングランド】 内より引用

標準ライブラリ関数を使い、乱数を作り出す。
0 からRAND_MAX という記号定数の間の乱数が生成され、戻り値として返る。
RAND_MAX 定数は、<stdlib.h>ファイルに定義されている。
この値を再定義する事により、生成できる乱数の範囲を広げたりできる。
また、rand 関数は、呼ばれる度にランダムな数値が生成されが
乱数系列を変えない限り、同じ順番で乱数が生成される。

乱数系列を変えるには、srand 関数を使う。
void rand(unsigned int seed);
seed に乱数系列を指定する。
通常のプログラムでは、常に乱数系列を変えた方がいい場合が多いので、
毎回、違う乱数系列にする。
毎回違う乱数系列にする時に適している値は、現在時間

以上 趣味のプログラミングで楽しく遊ぼう【プログラミングランド】 内より引用
===================================================================
srand( (unsigned int)time(NULL) );

return 制御文
・関数をそこで中断し、呼び出し元に制御を戻す働きがある。<猫
・呼び出しもとの関数にreturnの後ろの数値または変数の値を渡して関数を終了する文。<ウィキ

sizeof 演算子

==================================================================
以下 趣味のプログラミングで楽しく遊ぼう【プログラミングランド】内より引用

sizeof演算子は、指定したオブジェクトの大きさをバイト単位で返す演算子です。

主に配列や構造体の大きさを知りたい時に使います。


struct hito {
   char name[10];
   int age;
};

   int i;
   char cDATA;
   short sDATA;
   int iDATA;
   int array[5];
   float fDATA;
   double dDATA;
   struct hito suzuki;

   i = sizeof(cDATA);   // i = 1
   i = sizeof(sDATA);   // i = 2
   i = sizeof(iDATA);   // i = 4
   i = sizeof(array);   // i = 20(4バイトx5)
   i = sizeof(fDATA);   // i = 8
   i = sizeof(dDATA);   // i = 16
   i = sizeof(suzuki);   // i = 14


ちなみにsizeof演算子が返すデータ型は、size_t型(unsigned int)となっていますが、
よほどの事がない限り、int型の変数で受け取っておけば問題はないと思います。


以上 趣味のプログラミングで楽しく遊ぼう【プログラミングランド】内より引用
==================================================================

sprintf 関数 #include <stdio.h>

sprintf (結果を記憶する配列, 書式文字列, 各種変換・・・);




sprintf_s 関数 #include <stdio.h>

int sprintf_s( char *buffer, size_t sizeOfBuffer, const char *format [, argument] ...

srand 関数 #include <stdlib.h>

乱数系列を変える。
擬似乱数の発生系列を変更する。

srand( (unsigned int)time(NULL) );

static 静的変数

==================================================================
以下 趣味のプログラミングで楽しく遊ぼう【プログラミングランド】内より引用

変数に static 指定子を付ける事で、その変数は静的変数となります。



静的ローカル変数

通常のローカル変数は、その関数から抜けると全て失われてしまいますが、

static 付きの静的変数とすれば、関数から抜けても値が保持されます。

また、この変数は、プログラムが終了するまで保持されます。



このプログラムでは、関数 show 内で静的変数 count が使用されています。

1回目のshow() で静的変数 count の初期化が行われ、countが1ずつ増えます。

2回目以降のshow() では、初期化は行いませんが、

前回のcount の値が保持されています。

出力は、1 2 3 となります。



静的グローバル変数

通常のグローバル変数は、どこからでも使用する事ができますが、

static 付きの静的変数とすれば、そのファイル内からのみ使用できます

つまり、別ファイルからは、使用できません。(externを使用してもダメ)

この変数もローカル変数と同様に、 プログラムが終了するまで保持されます。

program1.c
#include <stdio.h>

void show(void);

// 静的グローバル変数(定義・実体)
static int idata;

void main(void) {
   show();

}


program2.c
#include <stdio.h>

void show(void);

// グローバル変数(宣言・参照)
extern int idata;

void show(void) {
   idata = 10;       // エラーとなる。
   printf("%d\n", idata);  // エラーとなる。
}




以上 趣味のプログラミングで楽しく遊ぼう【プログラミングランド】内より引用
===================================================================

strcat 関数 #include <string.h>

文字列を連結する関数。

strcat001.c


strcmp 関数 #include <string.h>

2つの文字列を(辞書式に)比較する関数。

int strcmp( const char *str1 ,  const char *str2 );

辞書式に並べた時に
str1の方が前にあれば、マイナスの値を
後ろの方にあれば、プラスの値を
同じだと、0 を返す。<猫より


実行結果
 i = strcmp(str1,str2); の時
   str1の値の方が小さいです。
  iの値は -1 です。

 i = strcmp(str1,str3); の時
  str1とstr2は同じ値です。
  iの値は 0 です。

 i = strcmp(str2,str1); の時
  str1の値の方が大きいです。
  iの値は 1 です。

strcpy 関数 #include <string.h>

文字列をコピーする。

char * strcpy( char *str1 , const char *str2 );

str2のNULLまでを、str1へコピーして末尾にNULLを付ける。
(str1はstr2で上書きされ、末尾にNULLが付く。)
戻り値はstr1のアドレス。
str1の配列は十分に用意しておく必要がある。
str1 < str2 だと(文字列が多すぎた場合)動作は未定。


実行結果:AB (ABcでは、無い)

strcpy_s 関数 #include <string.h>

=======================================================================
以下 14歳からはじめる C言語オンラインゲーム プログラミング教室 内の解説引用

標準ライブラリのコピー関数には
memcpy(メモリーコピー) や strcpy(ストリングコピー)がある。
この2つの関数の違いは、文字列の末尾を表す「0」を無視するかしないかで
memcpy は、0 を無視して指定したバイト数文をコピーする。
文字列以外にも使える汎用的関数。
strcpy は、末尾の 0 までをコピーする。

strcpy_s関数は、第2引数にコピー先のサイズを指定する。

errno_t strcpy_s( char *strDestination,
  size_t number0fElements, const char *strSource );

コピー関数で連結する場合、連結先の文字列の末尾の位置と
連結する文字列の長さを調べなければならない。
strlen関数を使うと、文字列のバイト数を調べる事ができる。
半角文字は1バイト、全角文字は2バイト。

以上 14歳からはじめる C言語オンラインゲーム プログラミング教室 内の解説引用
=======================================================================
=================================================
以下 JPCERT コーディネーションセンター 内より引用

strcpy_s() 関数は、より安全にコピーを行うために
コピー先バッファのサイズも引数としてとる(「STR07-C. TR 24731 を使用し
文字列操作を行う既存のコードの脅威を緩和する」参照)。

int main(int argc, char *argv[]) {
  /* ... */
  char * prog_name;
  size_t prog_size;

  prog_size = strlen(argv[0])+1;
  prog_name = (char *)malloc(prog_size);

  if (prog_name != NULL) {
    if (strcpy_s(prog_name, prog_size, argv[0])) {
      /* strcpy_s() のエラーを処理 */
    }
  }
  else {
    /* メモリを確保できなかった場合のエラー処理 */
  }
  /* ... */
}

strcpy_s() 関数を使うことで
動的に割り当てられたメモリまたは静的に割り当てられた配列との間でデータをコピーできる。
十分な領域がない場合、strcpy_s() はエラーを返す。

以上 JPCERT コーディネーションセンター 内より引用
=================================================


==========================================

以下 UsefullCode.net 内より引用(画像は略)

ちょっと過激なタイトルだが...Visual Studio 2005でstrcpyを使うと以下のような警告が出る。

void	Test(void)
{
	char	pszText[256];

strcpy(pszText,"あいうえお");
}


「warning C4996: 'strcpy' が古い形式として宣言されました。
'strcpy' の宣言を確認してください。」というのはあくまでも警告であってエラーではない。
そのため...

#define _CRT_SECURE_NO_DEPRECATE

#define WIN32_LEAN_AND_MEAN // Windows ヘッダーから使用されていない部分を除外します。
// Windows ヘッダー ファイル:
#include <windows.h>


// C ランタイム ヘッダー ファイル
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>


void Test(void)
{
char pszText[256];


strcpy(pszText,"あいうえお");
}

というように「_CRT_SECURE_NO_DEPRECATE」の定義を一番初めにおこなっておけば
この警告は出ないし、プログラムもきちんと動く。
しかし、だからと言ってこれは警告を無視しているだけであって根本的な問題は何も変わっていない。


strcpyを使うと何が問題なのかと言うと、コピー先のバッファー容量が指定されていない点だ。
つまり

void	Test(void)
{
	//1バイトしか確保していない!
	char	pszText[1];

//8バイトも代入してる!
strcpy(pszText,"abcdefg");
}

こんなソースコードを動かしたときにいわゆるバッファーオーバーランという状態になる。

デバッグ環境であれば

こんなエラー画面が表示されてプログラムが途中で止まるし
リリースコードでは悪意を持った者の攻撃対象となりうる。

正直なところを言うと
普通のフリーソフトを作っている開発者や趣味でプログラミングをしている人
仕事であってもカスタムソフト的なこじんまりしたソフトを作っている場合には
そこまで考えてプログラムする必要はないと思う。
しかし最近は小さいソフト会社でも「セキュリティが高いソフト」を開発しているとうたっている。
内容をよくよく聞いてみると「保存データを暗号化してるからセキュリティが高い」とか
「SSLで通信してるからセキュリティが高い」というような感じで
ソフト全体の開発にセキュリティを意識しているというわけではなく
ほんの一部分だけセキュリティを意識しただけで
実は全然セキュリティが高くないソフトを販売していたりする。
今後セキュリティが少しでも高いソフトウエアを開発したいと思っている場合は
まずは手始めにstrcpyの使用で出るような警告部分を修正するといいだろう
(ちなみに私はセキュリティが本当に高いソフトを開発するだけの能力は
持ち合わせていないのでこんなことを書いていいものかとも思うのだが...)。

ではどのようにすれば警告が出なくなり(少しは)安全なソースコードになるかと言うと

void	Test(void)
{
	char	pszText[256];

strcpy_s(pszText,256,"あいうえお");
}

このようにstrcpyの代わりにstrcpy_sという関数を利用する。
この関数では第二引数にpszTextで確保されている大きさを渡すようにできている。
これにより、strcpy_s内部では文字列をコピーする前に
コピー先に十分な領域があるかをチェックすることができ
バッファーオーバーランを未然に防ぐことができる。


とは言うものの以下のようにするとやはり文字列のコピーに確保された容量が足りないため
エラーになることはなる。
しかしデバッグビルドではアサーションエラー、リリースビルドでは
単に強制終了になるなどバッファーオーバーランよりはましだ。

void	Test(void)
{
char pszText[1];

strcpy_s(pszText,1,"あいうえお");
}



strcpyに対してstrcpy_sが作られたように
wcscpyにはwcscpy_s、_tcscpyには_tcscpy_sが用意されている。
また、同じようにstrncpyにもstrncpy_s、_tcsncpyに_tcsncpy_s...
従来の関数名に「_s」を付加したものがある。
警告が出たときは無視せずに置き換えるようにしよう。

以上 UsefullCode.net 内より引用(画像は略)
==========================================

strlen 関数 #include <string.h>

======================================
以下 C言語プログラミング入門 より引用

定義

 size_t strlen(const char* str); 

strlen関数は引数strの文字数を返す関数です.
ただし文字列の最後のNULL文字はカウントに含まれません.
size_tというのはunsigned intとほぼ同じです. (環境依存なのでunsigned intとは限りません.)

#include <stdio.h>
#include <string.h>

int main(void)
{
        char source[20] = "hello";
        printf("文字列の長さは %d です\n", strlen(source) );
        return 0;
}

実行結果

 文字列の長さは 5 です


以上 C言語プログラミング入門 より引用
======================================

strncat_s 関数(C++) #include <string.h>

strncat の定義・解説

======================================
以下 C言語プログラミング入門 より引用
 char* strncat(char* str1, const char* str2, size_t n);

strncat関数は文字列str1の後ろにstr2の文字列をn文字分連結させる関数です.

#include <stdio.h>
#include <string.h>

int main(void)
{
    char dest[20] = "ABC";
    char source[20] = "DEFGH";

    strncat(dest, source, 3);
    printf("文字列:%s\n", dest); 
    return 0;
}

実行結果

 文字列:ABCDEF
以上 C言語プログラミング入門 より引用
======================================

strncat_s の定義・解説

=================================================
以下 JPCERT コーディネーションセンター 内より引用

STR07-C. TR 24731 を使用し、文字列操作を行う既存のコードの脅威を緩和する

ISO/IEC TR 24731 は、C の既存の標準関数に代わり
より安全に利用できるように設計された代替関数を規定している。
たとえば、ISO/IEC TR 24731 Part I (24731-1) は、strcpy()strcat()strncpy()
および strncat() の代替関数として
それぞれ strcpy_s()strcat_s()strncpy_s() および strncat_s() 関数を定義している。

ISO/IEC TR 24731-1 関数は
過去 10 年間に起きた広く知られている多数のセキュリティインシデントに対応して
レガシーコードの改善に役立てる目的で Microsoft によって作成された。
これらの関数はその後
プログラミング言語 C の国際標準化ワーキンググループ(ISO/IEC JTC1/SC22/WG14)へ
標準化のために提案された。

たとえば、strcpy_s() の関数原型は次のとおりである。

errno_t strcpy_s(
  char * restrict s1,
  rsize_t s1max,
  const char * restrict s2
);

関数原型は strcpy() に似ているが
コピー先バッファの最大長を指定する rsize_t 型の引数を 1 つ余分に取る。
(rsize_t 型の引数を取る関数は、引数の値が RSIZE_MAX を超えている場合に制約違反と診断する)。
極端に大きなオブジェクトサイズは
オブジェクトのサイズが正しく計算されなかったことを示していることが多い。
たとえば、負の数は、size_t のような符号なしの型に変換されたときに非常に大きな正の数となる。
このような理由から、オブジェクトサイズの範囲を制限してエラーを検出することが有効な場合がある。
アドレス空間が大きなマシンの場合、ISO/IEC TR 24731-1 は
RSIZE_MAX を、サポートされている最も大きなオブジェクトのサイズまたは (SIZE_MAX >> 1) のうち
小さいほうの値として定義することを推奨している。
これは、たとえこの制限が、正当な(ただし非常に大きい)オブジェクトよりも小さくてもである。
(「INT01-C. オブジェクトのサイズを表すすべての整数値には rsize_t または size_t を使用する」も参照)。

strcpy_s() は、意味規則も strcpy() に似ている。
入力違反エラーがなければ、strcpy_s() 関数はコピー元の文字列からコピー先の文字配列へ
終端の NULL 文字までの文字を NULL 文字も含めてコピーする。
この関数は、成功するとゼロを返す。

strcpy_s() 関数は、コピー元の文字列をコピー先へ
コピー先バッファをオーバーフローさせずに完全にコピーできた場合に限り成功する。
具体的には以下のチェックが行われる。

・コピー元とコピー先のポインタが NULL であるか。
・コピー先バッファの最大長が、ゼロか、RSIZE_MAX よりも大きいか
 またはコピー元文字列の長さ以下であるか。
・領域の重なり合うオブジェクト間のコピーはできない。

実行時制約違反が検出された場合、コピー先バッファが NULL ポインタではなく
その最大長が、ゼロよりも大きく RSIZE_MAX 以下であれば
コピー先文字列は NULL 文字列に設定され、関数はゼロ以外の値を返す。
次の例では、strcpy_s() 関数を使用して src1dst1 にコピーしている。

char src1[100] = "hello";
char src2[8] =  {'g','o','o','d','b','y','e','\0'};
char dst1[6], dst2[5];
int r1, r2;

r1 = strcpy_s(dst1, sizeof(dst1), src1);
r2 = strcpy_s(dst2, sizeof(dst2), src2);

しかし、8 文字からなる文字列全体をコピー先バッファにコピーするための十分な領域がないため
src2dst2 にコピーする呼び出しは失敗する。
結果として、r2 にはゼロ以外の値が代入され、dst2[0] には NULL 文字が設定される。

ISO/IEC TR 24731-1 関数を使用すると
コピー先バッファのサイズと追加される文字の最大数を指定する必要があるため
セキュリティ上の欠陥を引き起こす可能性は低い。
ISO/IEC TR 24731 Part II (24731-2、策定中) では、もう 1 つの方法として
関数の結果に対して十分なメモリを割り当てる関数が提案される予定である。
ISO/IEC TR 24731 関数は、コピー先文字列の NULL 終端も保証する。

ただし ISO/IEC TR 24731-1 関数を使ったとしても
コピー先バッファの最大長およびコピーする文字の数が間違って指定された場合
依然としてバッファオーバーフローを引き起こす可能性はある。
ISO/IEC TR 24731-2 関数を使うと解放しなくてはならないメモリを把握しずらくなり
メモリリークを引き起こすおそれがある。
それゆえ ISO/IEC TR 24731 関数は特別安全なわけではないが
脆弱性の予防を目的とした保守に用い、レガシーコードの脆弱性を低減する役には立つだろう。

違反コード

次のコードは、msg が長すぎる場合にバッファオーバーフローを引き起こし
msg が NULL ポインタの場合に未定義の動作を引き起こす。

void complain(const char *msg) {
  static const char prefix[] = "Error: ";
  static const char suffix[] = "\n";
  char buf[BUFSIZ];

  strcpy(buf, prefix);
  strcat(buf, msg);
  strcat(buf, suffix);
  fputs(buf, stderr);
}
適合コード (実行時検査)

次の解決法では、バッファオーバーフローは生じない。

void complain(const char *msg) {
  errno_t err;
  static const char prefix[] = "Error: ";
  static const char suffix[] = "\n";
  char buf[BUFSIZ];

  err = strcpy_s(buf, sizeof(buf), prefix);
  if (err != 0) {
    /* エラー処理 */
  }

  err = strcat_s(buf, sizeof(buf), msg);
  if (err != 0) {
    /* エラー処理 */
  }

  err = strcat_s(buf, sizeof(buf), suffix);
  if (err != 0) {
    /* エラー処理 */
  }

  fputs(buf, stderr);
}
適合コード (コンパイル時に部分的に検査)

次の解決法は、静的アサートを使用して
コンパイル時にいくつかのチェックを行っている。
(「DCL03-C. 定数式の値をテストするには静的アサートを使う」を参照)。

void complain(const char *msg) {
  errno_t err;
  static const char prefix[] = "Error: ";
  static const char suffix[] = "\n";
  char buf[BUFSIZ];

  /* 2 文字以上が
   * msg のために用意されていることを保証する。 */
  static_assert(sizeof(buf) > sizeof(prefix) + sizeof(suffix),
                "Buffer for complain() is too small");
  strcpy(buf, prefix);

  err = strcat_s(buf, sizeof(buf), msg);
  if (err != 0) {
    /* エラー処理 */
  }

  err = strcat_s(buf, sizeof(buf), suffix);
  if (err != 0) {
    /* エラー処理 */
  }
  fputs(buf, stderr);
}
リスク評価

C99 のセクション 7.21 やその他で定義されている文字列処理関数を使うと
深刻かつ悪用可能な脆弱性につながる。
ありがちなプログラミングエラーを引き起こしやすい。
TR 24731 関数を適切に使用することで、これらの問題の大部分を排除できる。

レコメンデーション 深刻度 可能性 修正コスト 優先度 レベル
STR07-C P12 L1
自動検出

LDRA tool suite V 7.6.0 はこのレコメンデーションの違反を検出できる。

参考情報
  • [ISO/IEC 9899:1999] Section 7.21, "String handling <string.h>"
  • [ISO/IEC PDTR 24772] "TRJ Use of Libraries"
  • [ISO/IEC TR 24731-1:2007]
  • [Seacord 05a] Chapter 2, "Strings"
  • [Seacord 05b]
以上 JPCERT コーディネーションセンター 内より引用
=================================================

struct 構造体

異なったデータ型をひとまとめにして取り扱いたい時に使う。

C言語

struct 型名{

  メンバ変数の宣言

};
struct 型名 構造体変数名;

struct 型名{

  メンバ変数の宣言

} 構造体変数名;

typedef struct {

  メンバ変数の宣言

} 型名;
型名 構造体変数名;

C++

struct 型名{

  メンバ変数の宣言

};
型名 構造体変数名;

struct.c(例文)

time 関数 #include <time.h>

===============================
C言語講座:現在の年月日と時刻
===============================

を参照。

unsigned 修飾子

===========================
以下、C言語 - Wikibooksより

signed修飾子とunsigned修飾子

ここで、signed修飾子とunsigned修飾子の意味を考えましょう。
C言語の変数は型に規定された一定の数までしか表現できません。

標準的なbit数 範囲
char 8 -128〜127又は0〜255
short 16 -32768〜32767
int 16又は32 16bitの時は-32768〜32767、32bitの時は-2147483648〜2147483647
long 32又は64 32bitの時は-2147483648〜2147483647、64bitの時は-9223372036854775808〜9223372036854775807


この中で、short、int、longの3つの型は既にsigned修飾されています。
signed修飾とは「この変数は符号付きですよ」という修飾です。
逆にunsigned修飾を行うと「この変数は符号なしですよ」という修飾になります。
そうすると、範囲は次のようになります。

範囲
unsigned short 0〜65535
unsigned int 16bitの時は0〜65535、32bitの時は0〜4294967295
unsigned long 32bitの時は0〜4294967295、64bitの時は0〜18446744073709551615

以上、C言語 - Wikibooksより
===========================

void データ型

======================================
以下 c言語プログラムの基本形より引用
情報がないことを表す。
無効の意味。
void main(void)とは、「このメインルーチンは
オペレーティングシステムからなんの情報も受け取らず
またオペレーティングシステムに何の値も返さない」という意味を示している。
以上、c言語プログラムの基本形より引用
======================================

戻り値にvoid → 戻り値は無い。

void kansuu(int a, int b)

仮引数にvoid → 引数は無い。

int kansuu(void) { }

戻り値がある関数を呼ぶ時にvoid → 戻り値は無い。

int kansuu(void){

  return 0;
}

void main(void) {
  (void)kansuu();
}


while 制御文

==================================
以下 C言語 - Wikibooks 内より引用

while (式) {
 文
}

while (式) でいう式とは、返り値を持つものならどんなものでも用いることが出来るため
いろいろな表現を含むことが起こりえる。
while文は、式の値が真ならば、対応する文を実行し偽であるなら、実行しない。
式の値が最初から偽であった時には、対応する文は1度も実行されないことに注意。

以上 C言語 - Wikibooks 内より引用
==================================


ローカル変数
グローバル変数

==================================================================
以下 趣味のプログラミングで楽しく遊ぼう【プログラミングランド】内より引用

変数には、ローカル変数とグローバル変数がある。

関数内で宣言された変数をローカル変数と言い、
宣言された関数内でのみ使う事ができる。

一方、関数外で宣言された変数をグローバル変数と言い、
どこからでも使う事ができる。

趣味のプログラミングで楽しく遊ぼう【プログラミングランド】内のソース)



プログラムを作る上では、できる限りローカル変数を使い、
どうしても必要な場合だけグローバル変数を使うようにした方が良い。

以上 趣味のプログラミングで楽しく遊ぼう【プログラミングランド】内より引用
==================================================================

配列 同じ型のデータの集合

int hairetu[3] = {7,65,109}; 間違いが少ない→ int hairetu[ ] = {7,65,109};

  hairetu[0] → 7
  hairetu[1] → 65
  hairetu[2] → 109

1度に配列に値を代入するのは、宣言の時にしかできない。
後から値を代入したい時は、各々代入する。



ポインタ 変数のアドレスを記憶する変数

ポインタの解説や詳細は
「初心者のためのポイント学習C言語」サイト内のポインタ
「苦しんで覚えるC言語」サイト内の 15. ポインタ変数の仕組み
などのサイトや購入した本を参照させて頂いています。

ここでは、私がポインタの勉強をした過程(教本・参考サイト・自作お試しソース・その他)で
自分が解り易い様にした例文(ソース・プログラム等)を列挙していきます。
参照にさせて頂いた教本やサイトなどの例文(ソース)につきましては
各ソースの冒頭で、お断りさせて頂きます。
ですので、あなたの環境で動く保障は皆無です。
あくまでも、自己責任って事で!

って事で、

OS:Win7(Pro 32bit)
環境: VC++2008(SP1)

私が理解できた、簡単なC言語基礎プログラムから
簡単な例文だと思われるポインタを盛り込んでのソースを
自分なりに試しながら、別ページで自己解析(勝手にお試し)してみます。
つまり今後、自分が解り易い様に「ポインタ」についての例文の列挙です。

poi_try001.c

結果
 グー
 チョキ
 パー

poi_try002.c

結果:ムンバさん

poi_try003.c

結果:
 変数munbaの要素数:6
 変数sanの要素数:4
 変数munbasanの要素数:10

 文字列の連結:ムンバさん
 連結後の合計要素数:10



プログラミングの館