【C言語入門】mallocの使い方(memset, memcpy, free, memcmp)

みなさんmallocを使ってますか?

mallocは配列や構造体のメモリを動的に確保するために使用する関数です。

mallocを使って動的にメモリを扱いたい

確保したメモリ領域を関数を使って操作したい

今回はそんな人たちに向けて、以下のような内容をまとめました。

  • [基本]mallocとは
  • [基本]mallocの使い方について
  • [応用]memsetの使い方
  • [応用]memcpyの使い方
  • [応用]memcmpの使い方

mallocで確保したメモリはmemsetmemcpymemcmpなどの関数を使って初期化、コピーもしくはバイト単位での比較が可能です。汎用性の高い処理を書くために、必要な技術です。

ぜひmallocについて、詳しくなりましょう!

また、長い説明は要らない、使い方だけ知りたい!そんな方は以下のリンク先に、情報をひとまとめにしておきましたので、そちらをご覧ください。

>>> シンプルに「関数の引数など」を知りたい方はこちら

mallocとは

mallocとは動的メモリを確保する関数です。

ヘッダーファイル「stdlib.h」で宣言されています。引数で指定するバイト数分のメモリが確保され、確保したメモリ領域へのポインタを返します。

確保したメモリはfree関数で必ず解放する必要があります。

mallocの使い方について

配列や構造体のように要素数やメンバによって確保するメモリの量が異なる場合について、mallocを使ってメモリを確保する方法について説明します。

malloc関数を使用するにはヘッダーファイル「stdlib.h」をインクルードする必要があります。mallocの引数にはsizeof関数を使って構造体の型や配列の要素数を指定し必要なバイト数を入力します。これを構造体の型のポインタや配列のポインタでキャストして使用します。

なお、確保したメモリはfree関数を使って解放するのを忘れないようにしましょう。

実行結果:

このサンプルコードではint型と文字列ポインタをメンバに持つstrct型の構造体を宣言しています。malloc関数を使ってstrct型のサイズのメモリを確保し、strct型ポインタにキャストしています。

また文字を入れるための「char型の領域」を32個分メモリ上へ確保し、文字列ポインタにキャストしています。sprintf関数を使って文字列ポインタに文字列を指定し、printf関数を使って文字列を表示しています。

最後にfree関数を使ってメンバの文字列ポインタと構造体の実体のメモリを解放しています。

その他の関数の使い方について

malloc関数を使って確保したメモリを扱う関数について説明します。メモリを扱う関数にはmemsetmemcpymemcmpなどの関数があります。

memsetの使い方について

memset関数は主にメモリを初期化する場合に使用します。

memset関数を使用するにはヘッダーファイル「string.h」をインクルードする必要があります。

memset関数の第1引数にはメモリを設定するオブジェクトのアドレスを、第2引数にはメモリにセットする値を、第3引数にはメモリにセットする値の文字数を入力します。

実行結果:

このサンプルコードではmalloc関数を使ってメモリのサイズの変更を行い、その後memset関数を使って文字列のバイト数分だけNULL文字(\0)でメモリの値を書き換えています。

NULL文字で書き換えた文字列ポインタを出力表示していますので、空行が1列出力されています。

memcpyの使い方について

memcpy関数を使って構造体の実体をコピーする方法を説明します。

memcpy関数は第1引数にコピー先のアドレス、第2引数にコピー元のアドレス、第3引数にはコピーするバイト数を入力します。オブジェクト全体をコピーする場合、第3引数はコピー元のオブジェクト全体のバイト数となります。

memcpy関数でコピー元が構造体の場合にメンバにポインタを持っていると注意する必要があります。memcpy関数を使って構造体全体をコピーするとメンバのポインタは浅いコピーとなり、コピー元の値を参照します。

したがってコピー元のポインタ先の値が変われば、コピー先のポインタの値も一緒に変わります。深いコピーをするためにはメンバのポインタは個別にコピーをする必要があります。

サンプルコードで確認しましょう。

実行結果:

このサンプルコードではmemcpy関数を使って、構造体の実体「entity」を「copy_entity」にコピーしています。

このままではcopy_entityのメンバ「str」の値はentityのメンバ「str」の値を参照します。entityのメンバ「str」の値を変更すると、copy_entityのメンバ「str」の値も一緒に変わっています。

そこで値を参照せず深いコピーにするために、メンバの「str」はstrcpy関数を使って個別にコピーをしています。個別のコピー後にコピー元のentityのメンバ「str」の値を変更しても、copy_entityのメンバ「str」の値は変更されず、深いコピーができています。

memcmpの使い方について

memcmp関数を使うと指定バイト数のメモリ領域を比較することができます。

memcmp関数の第1引数と第2引数には比較するオブジェクトのポインタを、第3引数には比較するバイトサイズを指定します。memcmp関数はint型の値を返し、戻り値が0(ゼロ)の場合は比較の結果オブジェクトは一致と判定され、それ以外の値の場合はオブジェクトは不一致と判定されます。

今回はシンプルなサンプルで見ていきましょう。

実行結果:

このサンプルは非常にシンプルです。

str1・str2という二つのポインタ変数を用意し、それを比較しているだけですね!

[補足]memcmpによる構造体の比較

memcmp関数は構造体ではなく、シンプルサンプルで使い方をみてきました。

実はmemcmp構造体の実体を比較することは推奨されていません。パディングにより比較結果に不具合が発生する可能性があるからです。

パンディングとは奇数個の要素をもつchar型配列をメンバとしてもつ場合に、処理環境によっては1バイト空領域を追加して偶数個に揃える処理のことです。

これによりあるメンバのアドレス先からズレが生じることもありますので、memcmp関数を使って評価するのは避けましょう。比較を行いたい場合は、自作の関数を用意し、各メンバ変数の比較を行うのがメジャーな手法です。

その際は、以下の記事の「比較演算する方法」項目を参考にしてみてください。

【C言語入門】構造体の使い方(struct、ポインタ、アロー演算子)
更新日 : 2019年4月20日

各関数の使い方をひとまとめ

最後に復習として、各関数の使い方ををシンプルに一通りみてみましょう。

動的に確保する「malloc関数」

メモリを確保するなら、malloc関数です。使い方は、引数に確保したいバイト数を指定するだけでしたね!

また使い終わったら必ずfree関数で解放を行いましょう。動的にメモリを確保したら、ちゃんと解放する。

確保と解放はワンセットです。

データを埋めるなら「memset関数」

memset関数は、指定した領域を、指定した値で全て上書きしてくれる関数です。

主に初期化に使われる関数です。

引数:

第一引数・・・対象のメモリのポインタ
第二引数・・・上書きする値を指定
第三引数・・・上書きするバイト数

コピーするなら「memcpy関数」

データのコピーならばmemcpy関数を使用しましょう。

引数:

第一引数・・・コピー先のポインタ
第二引数・・・コピー元のポインタ
第三引数・・・コピーするバイト数

比較するなら「memcmp関数」

二つの指定した領域が同じかどうかはmemcmp関数で比較できます。同じ場合は、0が戻り値として取得でるので、それをif分で判定しましょう。

また本編で説明があったように、構造体の比較は正確に行えないので注意しましょう。

引数:

第一引数・・・比較するポインタ1
第二引数・・・比較するポインタ2
第三引数・・・比較するバイト数

まとめ

ここでは、mallocの使い方について説明しました。

またmemsetmemcpymemcmpといった関数を使ってメモリを操作する方法について説明しました。ポインタをメンバに持つ構造体についてmemcpy関数を使ってコピー操作する場合は実体全体のコピーでは浅いコピーとなるので注意しましょう。

使いこなすことができるように、この記事を何度も参考にして下さいね!

LINEで送る
Pocket

最短でエンジニアを目指すなら侍エンジニア塾

cta_under_bnr

侍エンジニア塾は業界で初めてマンツーマンレッスンを始めたプログラミングスクールです。これまでの指導実績は16,000名を超え、未経験から数多くのエンジニアを輩出しています。

あなたの目的に合わせてカリキュラムを作成し、現役エンジニア講師が専属であなたの学習をサポートするため効率よく学習を進めることができますよ。

無理な勧誘などは一切ありません。まずは無料体験レッスンを受講ください。

無料体験レッスンの詳細はこちら

書いた人

長野 透

長野 透

熊本在住のフリープログラマ兼ライターです。C/C++/C#、Java、Python、HTML/CSS、PHPを使ってプログラミングをしています。専門は画像処理で最近は機械学習、ディープラーニングにはまっています。幅広くやってきた経験を活かしてポイントをわかりやすくお伝えしようと思います。
お問合せはこちらでも受け付けています。
[email protected]

おすすめコンテンツ

あなたにぴったりなプログラミング学習プランを無料で診断!

プログラミング学習の効率を劇的に上げる学習メソッドを解説