-
なぜC/C++の構造体のsizeofは各メンバーのサイズの合計と一致しないのか?パディングとアライメントの仕組みを解説
sizeof() 演算子で取得できる構造体のサイズは、必ずしも各メンバーのサイズの合計と一致するとは限りません。コンパイラは、メモリのアライメント(整列)に関する問題を回避するために、メンバーの間や構造体の末尾にパディング(埋め草バイト)を自動的に挿入することがあります。その結果、構造体全体のサイズは見かけの合計よりも大きくなるのです。 パディングが挿入される代表的なケースは次のとおりです。 あるメンバーの直後に、より大きなアライメント要件を持つメンバーが続くとき 構造体全体のサイズを最大アライメント値の倍数に揃えるため、末尾に追加されるとき アライメントの制約はコンパイラによって異なり、
-
C/C++の前方宣言(フォワード宣言)とは?使える場面と仕組みを解説
C++における前方宣言(フォワード宣言)とは、クラスや関数の実際の定義より前に、その存在だけをコンパイラに知らせる仕組みです。前方宣言によって、宣言以降のコードは「Personという名前のクラスが存在する」ことを認識できるため、コンパイラは名前を見つけてもエラーを出さずに処理を進められます。クラスの実体(定義)自体は、後の段階でリンカによって解決されます。前方宣言のコード例class Person; // 前方宣言 void myFunc(Person p1) { // ... } class Person { // クラスの定義 // ここにクラスの内容を記述 };この例
-
C/C++標準規格のドキュメントはどこで入手できる?購入方法と無料ドラフト一覧
はじめに CやC++の標準規格(ISO/IEC文書)は、ISO(国際標準化機構)の公式ストアから有料で購入できます。しかし、多くの場合、ほぼ完成形となる最終草案(ドラフト)が無料で公開されているため、実質的に無償で内容を確認することも可能です。 この記事では、現在および過去の主要なC/C++標準規格について、「購入して入手する方法」と「無料で閲覧する方法」の両面から整理して紹介します。 C言語の標準ドキュメント C11(ISO/IEC 9899:2011) 購入:198スイスフラン(CHF)― ISO公式ページ 無料ドラフト:N1570(最終草案)― open-std.org(PDF)
-
C言語で数値を文字列に変換するプログラムの書き方
この記事では、C言語において数値(整数型・浮動小数点型など、あらゆる数値型データ)を文字列に変換する方法を解説します。変換のロジックは非常にシンプルです。ここでは sprintf() 関数を使用します。この関数は、値や文字列をコンソールではなく、文字列バッファに出力(格納)するために使われます。printf() との唯一の違いはこの点です。sprintf() の第1引数には、変換結果を保存したい文字列バッファを指定します。入力: ユーザーが数値(例:42.26)を入力する 出力: プログラムはその数値に対応する文字列(例:42.26)を返すアルゴリズムステップ1: ユーザーから数値を入力として
-
strcpy()関数を使わずに文字列をコピーするC言語プログラム
この記事では、strcpy()関数を使用せずに文字列を別の文字列へコピーする方法を解説します。この問題を解決するには、strcpy()と同じ働きをする独自の関数を作成する方法もありますが、ここでは少し工夫をして、別の標準ライブラリ関数を活用して文字列をコピーしてみましょう。基本的な考え方ロジックは非常にシンプルです。ここで使用するのはsprintf()関数です。sprintf()は、コンソール画面ではなく文字列(バッファ)に対して値や文字列を出力(書き込み)するための関数です。これがprintf()との唯一の違いです。第1引数には、データを保存したい文字列バッファを指定します。入力: 文字列「
-
引用符なしで文字列を出力するCプログラムの書き方
C言語には一風変わった課題がいくつかありますが、そのひとつが「引用符(ダブルクォーテーション)を一切使わずに文字列を出力する」というものです。通常、文字列リテラルを扱うには Hello World のように引用符で囲む必要がありますが、本記事ではマクロ関数を活用することで、これを実現する方法を解説します。 マクロ関数による文字列化の仕組み ポイントとなるのは、次のようなマクロ定義です。 #define getString(x) #x getString() はマクロ関数であり、引数 x を文字列に変換して返します。x の前に付けている # は、Cプリプロセッサにおける文字列化演算子(stri
-
C/C++マクロを使った文字列連結の方法
この記事では、C/C++のマクロを使って2つの文字列を連結する方法を解説します。マクロ内で2つ以上の文字列を定義し、それらを単純に続けて記述するだけで、コンパイル時に自動的に1つの連結文字列へと変換されます。これは、C言語の仕様として「隣接する文字列リテラルは連結される」という性質を利用したテクニックです。基本となる構文は以下の通りです。#define STR1 str1 #define STR2 str2 #define STR3 STR1 STR2 //str1とstr2が連結される入力: 2つの文字列を受け取ります出力: 連結された文字列を返しますアルゴリズムステップ1: 2つの文字列
-
C言語で浮動小数点数を文字列に変換する方法
この記事では、C言語において数値(整数・浮動小数点数など、あらゆる数値型データ)を文字列に変換する方法を解説します。考え方は非常にシンプルです。ここでは sprintf() 関数を使用します。sprintf() は、値や文字列をコンソールではなく「文字列」に対して出力するための関数です。これが printf() との唯一の違いです。第一引数には、変換結果を保存したい文字列バッファ(char型配列)を指定します。入力と出力のイメージ入力: ユーザーが数値(例: 42.26)を入力 出力: プログラムはその数値に対応する文字列 42.26 を返すアルゴリズムステップ1 − ユーザーから数値を受け取
-
C言語・C++で文字列を反転(逆順)する方法をわかりやすく解説
この記事では、文字列をその場(in-place)で反転する方法について解説します。反転処理の際に別のメモリ領域を確保せず、元の配列内で直接文字を入れ替えていくのがポイントです。C++であれば std::string を利用できますが、C言語の場合は文字型配列(char配列)を使って文字列を扱う必要があります。本プログラムでは文字配列で文字列を受け取り、それを反転して表示します。入力:文字列 This is a string 出力:反転後の文字列 gnirts a si sihTアルゴリズムreverse_string(str)入力 − 反転対象の文字列出力 − 反転された文字列基本的な考え方は
-
C/C++で整数オーバーフローを検出する方法|安全な実装テクニックを解説
C/C++において整数のオーバーフローを確実に防ぐ唯一の安全な方法は、演算が行われる前にオーバーフローが発生しないかをチェックすることです。ただし、いくつかのトリッキーな手法を使えば、オーバーフローを検出することも可能です。符号なし整数の加算でオーバーフローを検出する例として、unsigned int同士の加算におけるオーバーフロー検出を見てみましょう。加算結果が、足し合わせたどちらか一方の値よりも小さくなっていれば、オーバーフローが発生したことになります。サンプルコードunsigned int x, y; unsigned int value = x + y; bool overflow =
-
C/C++プログラムで発生するセグメンテーション違反とは?原因と対策を解説
セグメンテーション違反(Segmentation Fault)とはセグメンテーション違反とは、プログラムがアクセスを許可されていないメモリ領域にアクセスしようとした際に発生するエラーです。言い換えれば、オペレーティングシステム(OS)がプログラムに割り当てたメモリ範囲を超えて、不正な領域を読み書きしようとしたときに起こります。このエラーが発生すると、OSはプログラムを強制終了させるため、実行中のアプリケーションが突然クラッシュする原因となります。セグメンテーション違反の主な原因セグメンテーション違反は、主に以下のようなポインタの誤った扱いによって引き起こされます。1. 初期化されていないポイン
-
C/C++の関数からローカル配列を返す方法をわかりやすく解説
C++では、関数内で宣言したローカル配列をそのまま返すことができません。ローカル変数は関数の終了とともに破棄されるためです。この問題を解決するには、new演算子による動的メモリ確保を利用します。ここでは、関数から動的に確保した配列を返すC++プログラムを紹介します。ローカル配列を直接返せない理由関数内で宣言された通常のローカル配列は、スタック領域に格納されます。関数が終了するとスタックフレームが解放され、配列へのポインタは無効なメモリ(ダングリングポインタ)を指すことになります。そのため、ローカル配列をそのまま返すのは未定義動作となり、プログラムのクラッシュや予期しない動作を引き起こす可能性が
-
【初心者向け】C/C++における多次元配列の初期化方法をわかりやすく解説
多次元配列とは、次元数が2以上ある配列のことです。本記事では、3×3×3の多次元配列におけるメモリ割り当ての仕組みと、実際に配列を初期化して内容を表示するC++プログラムを紹介します。下図は、次元が3×3×3の多次元配列に対するメモリ割り当ての戦略を示したものです。アルゴリズム多次元配列を初期化するプログラムは、以下の手順で構成されます。Begin 多次元配列の要素を初期化する 配列のサイズを出力する 配列の内容を表示する Endサンプルコード以下は、2行2列の二次元配列を初期化し、そのサイズと内容を出力するC++プログラムです。#include<iostream
-
C/C++の多次元配列とは?基本概念から動的メモリ確保まで徹底解説
C/C++における多次元配列とは、簡単に言えば「配列の配列」として定義されるデータ構造です。多次元配列では、データが表形式(行優先順/row-major order)でメモリ上に格納されます。 以下の図は、3×3×3の次元を持つ多次元配列のメモリ割り当て戦略を示したものです。 アルゴリズム 2次元配列を動的に確保し、操作するための基本的な手順は以下の通りです。 Begin 配列の次元を宣言する new演算子を使用して2次元配列 a[][] を動的に確保する 配列に要素を格納する 配列の内容を出力する deleteによってメモリを解放する End サン
-
sizeof演算子を使わずにC/C++で配列のサイズ(要素数)を求める方法
この記事では、C/C++において sizeof 演算子を使用せずに、配列のサイズ(要素数)を求める方法を解説します。ポインタ演算の仕組みを利用することで、配列の長さを動的に取得できます。アルゴリズムこの手法は、配列へのポインタと通常のポインタの違いを利用したものです。処理の流れは以下の通りです。Begin 配列の要素を初期化する。 &a => 配列全体へのポインタ。a と同じメモリアドレスを指すが、型が「配列」である点が異なる。 &a + 1 => 配列の終端の次のアドレスを指す。 *(&a + 1) => 参照外しにより、最後
-
C言語の構造体における柔軟な配列メンバー(Flexible Array Member)の使い方
柔軟な配列メンバー(Flexible Array Member)とは C言語の構造体における柔軟な配列メンバー(Flexible Array Member)とは、構造体内で配列のサイズ(次元)を指定せずに宣言できる特殊なメンバーのことです。実際のサイズは実行時に動的に決定されるため、「柔軟(フレキシブル)」と呼ばれます。 柔軟な配列メンバーを使用する際は、以下のルールを守る必要があります。 柔軟な配列メンバーは、必ず構造体の最後のメンバーとして宣言する 構造体には、柔軟な配列メンバー以外に少なくとも1つの名前付きメンバーが必要 この機能は C99規格 で標準化されている サンプルコード 以
-
C/C++における配列の短縮初期化表記(Shorthand Array Notation)の使い方
C言語では、配列の要素に同じ値が繰り返し含まれる場合、短縮配列表記(shorthand array notation)を使うことで、コードを簡潔に記述できます。この記事では、その基本的な書き方と動作について解説します。 サンプルコード #include <stdio.h> int main() { int array[10] = {[0 ... 3]7, [4 ... 5]6, [6 ... 9]2}; for (int i = 0; i < 10; i++) printf(%d , array[i]); return 0; } 実行結果 7 7
-
なぜC言語は配列パラメータをポインタとして扱うのか?効率性の観点から解説
なぜC言語は配列パラメータをポインタとして扱うのか? C言語では、関数へ配列を渡すとき、そのパラメータは自動的にポインタとして扱われます。これは、処理時間を短縮し、プログラムをより効率的に動作させるためです。 仮に配列の各要素のアドレスを1つずつ関数の引数として渡すことも可能ですが、その場合は要素の数だけ処理が必要となり、非常に時間がかかってしまいます。そこでC言語では、配列の先頭要素のアドレス(ベースアドレス)だけを関数に渡す方式が採用されています。先頭アドレスが分かれば、ポインタ演算によって残りのすべての要素へ順番にアクセスできるためです。 実際のところ、次の2つの関数宣言はコンパイラにと
-
【C/C++入門】ポインタ演算 *(array+i) を使った配列要素へのアクセス方法
この記事では、C++で配列の要素にアクセスする際の、あまり知られていない表現方法を紹介するシンプルなプログラムを解説します。#include<iostream> using namespace std; int main() { int array[5] = {7,7,7, 6, 6}; for (int i = 0; i < 5; i++) cout<<*(array+i); return 0; }出力結果7 7 7 6 6プログラムの解説通常、配列の要素には array[i] のような添字(インデックス)表記でアクセスします。しか
-
C言語のポインタと配列の違いを徹底解説!&演算子・sizeof・代入ルール
C言語において、ポインタと配列は多くの場面で同じように扱われます。しかし、両者にはいくつか重要な違いが存在します。本記事では、その違いを「&演算子」「sizeof演算子」「代入の可否」の観点から、サンプルコード付きでわかりやすく解説します。 &演算子の挙動の違い &pointer:ポインタ変数自体のアドレスを返します。 &array:配列の先頭要素のアドレスを返します。 sizeof演算子の挙動の違い sizeof(array):配列の全要素が消費するメモリの合計サイズを返します。たとえば int a[10]; の場合、int型が4バイトの環境では40