【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関数を使ってコピー操作する場合は実体全体のコピーでは浅いコピーとなるので注意しましょう。

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

C言語カリキュラム無料公開中!

この記事はC言語入門完全攻略ガイド【基礎学習/応用学習/キャリア形成】の一部になります。このカリキュラムは、プログラミング入門者が、基礎学習から応用学習、さらにはキャリア形成まで体系的に学べる内容となっています。

C言語学習に必要な情報を一つにまとめていますので効率よくC言語を学ぶことが出来ます。この機会に是非活用していただければと思います。

C言語入門完全攻略ガイド【基礎学習/応用学習/キャリア形成】
更新日 : 2018年5月22日

C言語を最短で習得したい方へ

元々ITリテラシーの高い方やプログラムの学び方がわかっている方であれば、この記事通りに進めていけば、C言語を独学で習得することができるでしょう。

ただし、実際の学習期間中はつまづいている時間がほとんどです。

「なかなかやり遂げられ無い、挫折してしまった」
「時間が足りない」
「情報が少なくどう調べればいいかわからない」
「エラーを解決することができない」

このような悩みを抱えている方も少なく無いと思います。

もう挫折したくない
本業と両立しながら、好きな時間で自分のペースで勉強を続けていきたい
自分だけのカリキュラムで効率的に勉強したい
そんな方はお気軽に侍エンジニア塾までご相談ください。

お一人お一人に専属のインストラクターがつくので、通常のスクールでは難しい、AI(人工知能)や機械学習、IoTについて学習することできます。

まずは『無料体験レッスン』で、弊社のコンサルタントと一緒にあなた専用の学習方やカリキュラムを考えてみませんか?

C言語ならではの学習方法や、現役エンジニアから貴重なアドバイスを受けることができます。

詳しくは下の画像をクリックして弊社サービス内容をご確認ください。

cta_c2

非常識な結果を出す卒業生多数!

エンジニアキャリア戦略

人気記事セレクション

3000名以上来場の人気セミナーが開催決定

18歳で時給6000円だった侍エンジニア塾代表の木内より、『プログラミングで人生を変える』ための学習方法をお教えます。

0からプログラミングを習得し、フリーランスエンジニアになる方法プログラミング学習の効率を劇的に上げる学習メソッドを解説しますので、奮ってご参加ください。

  • 日付:4/20(土),4/27(土)
  • 時間:14:00〜17:35終了予定
  • 場所:当社 道玄坂オフィス
  • 住所:〒150-0043 東京都渋谷区道玄坂2丁目11-1 Gスクエア渋谷道玄坂 4F *Googleマップでは「東京都渋谷区道玄坂2丁目11-1」で検索してください。近隣にスクエア渋谷という別のビルがあるためご留意ください。
  • 参加費:無料
  • URL:https://seminar.sejuku.net/
詳しくは下の画像をクリックして弊社セミナー内容をご確認ください。

LINEで送る
Pocket

この記事が気に入ったら
いいね!をしてフォローしよう

最新情報をお届けします

書いた人

長野 透

長野 透

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