-
C言語の変数のメモリ表現を表示する方法
本記事では、C言語の変数がメモリ上でどのように表現されているかを表示する方法を解説します。整数(int)、浮動小数点数(float)、ポインタの3種類について、それぞれのバイト単位のメモリ内容を出力してみましょう。変数の内部表現を確認することで、エンディアン(バイトオーダー)やデータ型ごとのサイズなど、低レベルな挙動への理解を深めることができます。解決の手順この問題は、以下の手順に従って解決します。対象となる変数のアドレスとサイズを取得するそのアドレスを unsigned char * 型にキャストし、バイト単位でアクセスできるようにする変数のサイズ分だけループ処理を行い、キャストしたポインタ
-
C言語で独自のsizeofを実装する方法を解説
C言語のsizeof演算子は、変数やデータ型が占めるバイト数を取得するために使われます。実は、この仕組みはポインタ演算の性質を利用すれば、マクロを使って自分でも再現することができます。この記事では、独自のmy_sizeofマクロを実装する方法を詳しく解説します。基本的な考え方まず、変数xのアドレスを&xで取得することを考えてみましょう。ここで&x + 1とすると、ポインタは「1つ先」に進みますが、その進み幅はデータ型によって異なります。1バイトだけ進む → char型4バイト進む → int型やfloat型8バイト進む → double型などつまり、(&x + 1)と&
-
C言語で浮動小数点数のセットビット数を数える方法を解説
この問題では、1つの浮動小数点数が与えられ、その2進表現におけるセットビット(1になっているビット)の数を求める必要があります。例えば、浮動小数点数が 0.15625 の場合、セットビットは6個になります。一般的なCコンパイラでは、単精度浮動小数点形式で数値が表現されるため、メモリ上では次のようなビット列として格納されます。考え方:ポインタとバイト単位での処理浮動小数点数をビット値に変換して調べるには、まず対象の数値をポインタ変数に渡し、そのポインタを char* 型にキャストします。こうすることで、float型のデータを1バイトずつ順番に処理できるようになり、各バイト(char型)ごとのセッ
-
putchar()のみを使用してC言語でlong intを出力する方法
はじめにここでは、C言語においてputchar()関数のみを使ってlong int型の値を出力する方法を解説します。通常、変数の値を出力する際にはprintf()関数を利用すれば簡単ですが、今回は「putchar()以外の関数は使用できない」という制約が課されています。ご存知のとおり、putchar()関数は1文字だけを出力できる関数です。そこで、この関数を活用して数値の各桁を1文字ずつ出力していきます。具体的には、数値から1桁を取り出した際に、文字0(ASCIIコード48)を加算することで、その数字に対応するASCII文字へと変換します。実装のポイント数値を桁ごとに出力するためには、再帰呼び
-
main()関数なしで動作するCプログラムの書き方
C言語のプログラムは、main()関数がなくても実行できるのでしょうか?答えは「はい」です。実は、main()を持たないプログラムを書くことが可能です。一般的に、main()はプログラム実行のエントリーポイント(開始地点)であると説明されます。これはあくまでプログラマーの視点から見た話で、実際にはシステムの視点では異なります。システムはまず_start()を呼び出して実行環境をセットアップし、その後main()を呼び出します。つまり、この_start()を自前で定義すれば、main()が存在しなくてもプログラムを動作させられるのです。サンプルコード#include <stdio.h>
-
C言語で独自のmemcpy()関数を自作する方法
この記事では、C言語で標準ライブラリのmemcpy()関数と同等の機能を自前で実装する方法を解説します。memcpy()は、あるメモリ領域から別のメモリ領域へデータブロックをコピーするための関数であり、文字列や配列など任意のデータの複製に広く使われています。memcpy()の基本構文まず、標準ライブラリにおけるmemcpy()のプロトタイプを確認しておきましょう。void *memcpy(void *dest, const void *src, size_t num);dest:コピー先のメモリ領域へのポインタsrc:コピー元のメモリ領域へのポインタ(const修飾により書き換え不可)num:
-
C言語でブール値(bool)を扱う方法:enumを使った実装例
C言語には、他の多くのプログラミング言語のような組み込みのブール型(bool)が標準では用意されていません。しかし、enum(列挙型)を活用することで、独自のブール値を簡単に定義できます。 enumによるbool型の作成 まず「boolean」という名前の列挙型を作成し、その要素として「false」と「true」を定義します。列挙子は宣言された順に0から順番に値が割り当てられるため、先頭のfalseは0、2番目のtrueは1という値を持つことになります。これにより、boolean型をあたかもブール型であるかのように扱えるようになります。 コード例 #include<stdio.h>
-
C言語プログラミングの意外な事実5選 ― 知ると楽しくなる仕様のトリビア
C言語には、一見すると奇妙に見えるのに、実際には言語仕様として正しい動作をするユニークな特徴がいくつか存在します。この記事では、Cプログラミングに関する興味深い事実を、実際のコード例と実行結果とともにわかりやすく解説します。 1. switch文のcaseラベルはif-else文の中に置ける switch文のcaseラベルは、実はif-else文の中に配置することも可能です。caseラベルは単なるジャンプ先の目印(ラベル)にすぎないため、構文上許される位置であれば自由に書けるのです。 サンプルコード #include <stdio.h> main() { int x =
-
C/C++のnextafter()関数とnexttoward()関数の違いと使い方
本記事では、C/C++で利用できる nextafter() 関数と nexttoward() 関数の動作について詳しく解説します。これらの関数は、C言語では math.h、C++では cmath ライブラリに含まれています。 これらの関数は nextafter(a, b) や nexttoward(a, b) の形式で呼び出し、「a から b の方向へ進んだ、次に表現可能な浮動小数点数」を返します。両者の主な違いは、nexttoward() の第2引数 b が long double 型として扱われ、より高い精度で方向を指定できる点です。 サンプルコード #include <stdio.
-
【C言語】pthread_cancel()関数の使い方 – スレッドのキャンセル方法を解説
POSIXスレッド(pthread)プログラミングにおいて、pthread_cancel()関数は、指定したスレッドIDに対応する特定のスレッドをキャンセル(終了要求)するために使用されます。この関数は、対象のスレッドに対してキャンセル要求を送信し、スレッドの終了を促します。pthread_cancel()の構文pthread_cancel()の基本的な構文は以下のとおりです。int pthread_cancel(pthread_t th);引数には、キャンセルしたいスレッドのスレッドID(pthread_t型)を指定します。戻り値としては、成功した場合に0が返され、失敗した場合にはエラーコー
-
C言語のpthread_equal()関数の使い方を徹底解説
pthread_equal()関数とは pthread_equal()関数は、POSIXスレッド(pthread)ライブラリに含まれる関数の一つで、2つのスレッドが同一であるかどうかを判定するために使用されます。戻り値は0または非ゼロの値で、2つのスレッドが等しい場合は非ゼロの値を、等しくない場合は0を返します。 なお、スレッドID(pthread_t型)の比較には「==」演算子ではなく、必ずこのpthread_equal()関数を使用することが推奨されています。これは、pthread_t型の内部構造が処理系によって異なるため、移植性の高いコードを書くためです。 構文 pthread_equa
-
C言語のpthread_self()関数でスレッドIDを取得する方法
pthread_self()関数とはC言語のPOSIXスレッド(pthread)プログラミングでは、pthread_self()関数を使用することで、現在実行中のスレッド自身のID(スレッド識別子)を取得できます。この関数が返すIDは、システム上に存在するスレッドを一意に識別するために利用されます。ただし、注意すべき点があります。複数のスレッドが動作している環境で、あるスレッドが終了すると、そのスレッドが使用していたIDが新しいスレッドに再利用される場合があります。そのため、IDの一意性が保証されるのは「実行中のスレッド同士」の間だけです。サンプルコード以下は、メインスレッドと生成したスレッド
-
C言語におけるfork()とexec()システムコールの違いを徹底解説
はじめに:fork()とexec()とは本記事では、C言語におけるfork()とexec()システムコールの動作と、両者の違いについて詳しく解説します。fork()は、呼び出し元のプロセスを複製することで新しいプロセスを生成するシステムコールです。新しく生成されたプロセスは「子プロセス」と呼ばれます。子プロセスの主な特性子プロセスは独自のプロセスID(PID)を持ちます。子プロセスの親プロセスID(PPID)は、呼び出し元プロセスのPIDと同一になります。子プロセスは親プロセスのメモリロックやセマフォを継承しません。fork()の返り値は子プロセスのPIDです。返り値が0以外の場合は親プロセス
-
C言語とC++の主な非互換性5選|Cでは動くのにC++でエラーになるコード例
はじめに C言語とC++は高い互換性を持っていますが、完全に同じというわけではありません。ここでは、Cコンパイラでは問題なくコンパイル・実行できるのに、C++コンパイラではエラーになる代表的な非互換性のケースを、サンプルコードとともに解説します。 1. 旧式(K&Rスタイル)の関数定義 C言語では、引数リストの後ろに引数の型を記述する旧式の構文で関数を定義できます。しかし、この書き方はC++では無効です。 #include<stdio.h> void my_function(x, y)int x;int y; { // C++では無効 printf(&q
-
C言語の衛生的マクロ(Hygienic Macros)とは?識別子の意図しない捕捉とその回避策
衛生的マクロ(Hygienic Macros)とは本記事では、C言語における「衛生的マクロ(Hygienic Macros)」について解説します。C言語のマクロは、コードの重複を減らして処理を共通化できる便利な機能ですが、書き方を誤ると識別子が意図せず捕捉される(accidental capture)ことで、期待どおりの結果が得られない場合があります。次のコードは、その典型的な失敗例です。問題のあるコード例#include<stdio.h>#define INCREMENT(i) do { int a = 0; ++i; } while(0)main(void) { &n
-
C/C++における基本データ型と派生データ型の違いを徹底解説
プログラミング言語のCやC++では、データを扱うためにさまざまなデータ型が用意されています。これらは大きく「基本データ型」と「派生データ型」の2つに分類できます。この記事では、両者の違いを比較表とともにわかりやすく解説します。 基本データ型と派生データ型の比較表 基本データ型派生データ型 基本データ型は「プリミティブ型」とも呼ばれます。派生データ型は、基本データ型を組み合わせて構成されます。 int、char、float、void などが代表例です。配列、構造体、ポインタ、共用体などが該当します。 整数型・文字型には、int、char、signed int、signed char、u
-
C言語のFILEデータ型とは?オペーク型の正体と使い方を解説
FILEデータ型とはC言語でファイルを扱う際には、FILE型のポインタを使用します。つまり、FILEはデータ型の一つです。この型は「オペーク型(不透明型:Opaque datatype)」と呼ばれるもので、内部の実装詳細が隠蔽されています。プログラマはFILEの内部構造を直接操作するのではなく、fopen()やfgets()、fclose()といった標準ライブラリ関数を通じて間接的にファイルを操作します。FILEの具体的な定義は処理系(OSや標準ライブラリ)ごとに異なります。以下は、Ubuntuシステムで使用されているGNU Cライブラリ(glibc)におけるFILEの定義です。Ubuntuに
-
スレッド同期を使って複数スレッドで番号を順番に出力する方法(C言語・pthread実装例)
本記事では、複数のスレッドを使って数字を正しい順序で出力する方法を解説します。まず n 個のスレッドを作成し、それらを同期させます。基本的な考え方は、「1番目のスレッドが 1 を出力し、次に2番目のスレッドが 2 を出力する」というように、各スレッドが順番に担当する番号を出力していくというものです。あるスレッドが出力処理を行っている間は共有リソースがロックされるため、他のスレッドがその領域にアクセスすることはできません。 同期の仕組み:ミューテックスと条件変数 このプログラムでは、POSIX スレッド(pthread)が提供する次の2つの同期機構を利用しています。 ミューテックス(pthre
-
C言語でマルチスレッドを活用した線形検索の実装方法
ここでは、配列内の特定の要素を検索する際に、マルチスレッドの概念をどのように応用できるかを解説します。アプローチは非常にシンプルです。まず複数のスレッドを作成し、配列をいくつかの部分に分割します。そして、それぞれのスレッドが担当範囲の検索を行い、目的の要素が見つかった時点でフラグを立てて識別できるようにします。サンプルコード#include <stdio.h> #include <pthread.h> #define MAX 16 #define THREAD_MAX 4 int array[MAX] = { 1, 5, 7, 10, 12, 14, 15, 18, 2
-
C言語で厳密なエイリアシング(strict aliasing)が必要な理由とは?
はじめにC言語のプログラミングにおいて、「厳密なエイリアシング(strict aliasing)」の概念は非常に重要です。この記事では、なぜ厳密なエイリアシングを意識する必要があるのかを、実際のコード例を通じて解説します。まずは次のコードを見て、その出力結果を分析してみましょう。コード例#include<stdio.h> int temp = 5; int* var = &temp; int my_function(double* var) { temp = 1; *var = 5.10; //ここでtempの値が書き換えられる return (te