スキップしてメイン コンテンツに移動

投稿

2月, 2023の投稿を表示しています

exit(0)とreturn 0の違い

 hoge1関数内のexit(0)は、その場でプログラムを強制終了します。 hoge2関数内のreturn 0は、呼び出し元のmain関数に戻ります。

gets関数が廃止された理由

バッファオーバーフローの脆弱性があるため廃止されました。 fgets関数がgets関数の代替として利用できます。 ただし相違点はあります。 fgets関数は入力の改行文字がバッファに格納されます。 また入力ストリーム上にバッファが残ってしまう仕様です。

ポインタの戻り値

関数内のstaticなしで定義した変数は関数が終了すると解放されます。 自動変数領域のアドレスを関数の戻り値にすることはできません。 静的領域に割り付けられる文字列リテラルのアドレスは戻り値にすることができます。

関数内のstatic

関数内でstaticをデータ型の前に追加して変数を初期化すると、 その変数に対してプログラム終了時まで有効な静的領域が確保されます。 初期化は一度のみで、 関数が複数回呼び出された場合は、 前回に呼び出されたときの値が保持されています。

const

constをデータ型の前に追加して初期化すると 変数の値、配列の要素、ポインタが指し示す先の値が変更不可になります。 const int a = 5; const int b[] = {10,20}; const char s[] = "papa"; const char *p = "kingyo"; 以下はpの値が変更不可になります。 char * const p = "kingyo";

fopne()とopen()の違い

fopne()は高水準入出力、 opne()は低水準入出力としてファイルをオープンします。 高水準入出力はHDDなどの外部補助記憶装置へのアクセス回数を減らすためにメインメモリのバッファ領域を介してファイルの入出力を行います。 低水準入出力はバッファリングを行いません。

変数とアドレス

&aは5の格納先アドレスです。 &b[0]は10、&b[1]は20の格納先アドレスです。 bと&b[0]は等価です。 &s[0]は'p'、&s[1]は'a'の格納先アドレスです。 sと&s[0]は等価です。 &dt.noは100の格納先アドレスです。 &dtと&dt.noは等価です。

安全なポインタの使い方

 ①変数宣言時にNULL(0番地)で初期化します。 int a = 5; int *p1 = NULL; p1 = &a; ②指し示す先を参照する前にNULLチェックします。 if(p1 != NULL){printf("%d\n",*p1)}; ③指し示す先のメモリを解放したらNULLを代入します。 free(p2); p2 = NULL;

ダブルポインタ

ダブルポインタはポインタのポインタです。変数の前に「**」をつけて宣言します。 int a = 5, *p, **PP; p = &a; pp = &p; *p:pが指し示す先の値(aの値) *pp:ppが指し示す先の値(pの値) **pp:ppが指し示す先が指し示す先の値(aの値)

文字列をポインタで管理

 char *p1 = "Hello"; p1に文字列の先頭アドレスが格納されます。 printf("%s\n",p1); static char *p2[] = {"Papa","Kingyo"}; p2[0]、p2[1]に各文字列の先頭アドレスが格納されます。 printf("%s\n",p2[0]); printf("%s\n",p2[1]);

文字列を配列として格納

 static char str1[] = "Papa"; 配列名は文字列が格納されている先頭アドレスです。 printf("%s\n",str1); static char str2[][10] = {"Papa","Kingyo"}; 配列名[添字]は各文字列が格納されている先頭アドレスです。 printf("%s\n",str2[0]); printf("%s\n",str2[1]);

ポインタを理解する

初期化した変数aとポインタ変数pを宣言します。 int a = 5, *p; pにaのアドレスを格納します。 このとき、pはaを指し示すといいます。 p = &a; *pでpが指し示す先の値を参照できます。 pが指し示す先はaです。 printf("*pの値 = %d\n",*p);

加算による減算

 引く数の補数を用いると減算を加算で表現できます。 例えば「15-8=7」について、 引く数「8」の補数「2」を用いて、加算で表現すると「15+2=17」となります。 結果「17」の最上位の桁を取り除くと「7」となり、 減算の結果と同じになります。 2進数の減算 例えば「6-2=4」を4ビットの2進数で加算表現します。 「6」は「0110」、「2」は「0010」で、 その補数は「1110」だから「0110」+「1110」=「10100」となります。 5ビットの「1」は、桁あふれなので無視すると、 結果は「0100」となります。 「0100」は10進数の「4」です。

2進数の正負の数

 2進数の正⇔負の変換は、先頭に「+」「-」を付けるのではなく、2の補数で行います。 例えば、10進数の「3」は、4ビットの2進数で「0011」ですが、 「0011」の2の補数「1101」が、10進数の「-3」であり、 「1101」の2の補数「0011」が、10進数の「3」です。 符号付き2進数において最上位ビットは符号を表す符号ビットとして使用されます。 符号ビットが「0」だと正の数、「1」だと負の数になります。 <4ビットの2進数> 0000 0 0001 1 1111 -1 0010 2 1110 -2 0011 3 1101 -3 0100 4 1100 -4 0101 5 1011 -5 0110 6 1010 -6 0111 7 1001 -7             1000 -8

補数

ある数に対して、桁上がりさせることができる最小の数を補数といいます。 例えば、8の補数は2、85の補数は25です。 特に、10進数における補数を10の補数といいます。 10進数において、桁上がりさせない最大の数を「9の補数」といいます。 例えば、8の「9の補数」は1、85の「9の補数」は24です。 2進数における補数 例えば「0110」の補数は「1010」です。 「0110」に「1010」を足すと「10000」となって桁上がりさせます。 特に、2進数における補数を2の補数といいます。 2進数において、桁上がりさせない最大の数を「1の補数」といいます。 例えば「0110」の「1の補数」は「1001」です。 「0110」に「1001」を足すと「1111」となって桁上がりしない最大の数になります。 ビット反転させると「1の補数」になります。 「1の補数」に1を足すと「2の補数」になります。

ファイルディスクリプタ(fd)

 ファイルを識別するための整数値です。 stdin、stdio、stderrのfdはそれぞれ0、1、2になります。 ファイルオープンするとfdは3から順番に割り当てられます。 open()でオープンに成功するとfdを返す。 fopen()ではFILE構造体のメンバ「_fileno」でfdを確認できます。

乱数の生成

 void srand(unsigned int seed) time()で取得したtime_t型の整数値を符号なし整数型にキャストして乱数系列を初期化するseed値とします。 int rand( void ) 乱数は0からRAND_MAXの範囲内の擬似乱数を返します。

ヘッダファイルの格納場所

 gccでオプション-vを使ってコンパイルすればヘッダーファイルの格納場所を確認できます。 #include <...> search starts here:  /usr/lib/gcc/x86_64-linux-gnu/9/include  /usr/local/include  /usr/include/x86_64-linux-gnu  /usr/include End of search list.

2038年問題

 C言語で書かれてるシステムにおいて「time_t型」を32ビットの符号付き整数の範囲で扱っている場合は、1970年1月1日0時0分0秒から2147483647秒を経過した、2038年1月19日3時14分7秒を過ぎると、値がオーバーフローして、時刻を正確に扱えず、システムが誤作動する問題です。

time_t型

 1970年1月1日午前0時0分0秒からの経過秒数を扱うデータ型です。 値は32ビットまたは64ビットの符号付き整数の範囲です。 (32ビットの符号付き整数) -2147483648 ~ 2147483647 (64ビットの符号付き整数) -9223372036854775808 ~ 9223372036854775807

エスケープシーケンスによる画面制御

 ESCコードと [(角括弧)と制御文字列によって、文字に色をつけたり、カーソル位置を指定したりできます。

ヘッダファイルと標準ライブラリ

 printf( ) 関数のプロトタイプはヘッダファイル stdio.h に記述されています。 関数の定義(処理内容)は事前にコンパイルされた状態で標準ライブラリ libcに収録されています。 標準ライブラリ はコンパイル時に-lcを指定しなくても自動的にリンクされます。

関数のプロトタイプ宣言

 main()関数内で他の関数を呼び出す場合は、呼び出される関数の処理を事前に記述しておく必要があります。 ただし、以下のプロトタイプ宣言さえすれば、関数の処理は任意に場所に記述することができます。 <プロトタイプ宣言> 戻り値の型 関数名(引数の型,・・・);

コマンドライン引数

 int main(int argc, char *argv[])の引数のことです。 argcには引数の数、配列argvには引数の文字列が格納されます。