【C言語入門】strcpyとstrcpy_sの使い方(文字列のコピー)

strcpyって使ってますか?

strcpyは文字列型データをコピーするために使用する関数です。

文字列はchar型の配列やchar型のポインタとして扱われます。

文字列型のデータを数値型のデータのように「=」記号を使って代入コピーしようとしても、配列の場合は代入できなかったり、ポインタの場合はアドレス先をコピーすることになるなど、意図通りにならないので注意が必要です。

この記事では、文字列のコピーについて

  • 文字列の代入について
  • strcpyの使い方について
  • strcpyを使用する上での注意
  • strcpy_sの使い方

など、よくやりがちなコピーの内容から、関数を使った文字列のコピーについてまで解説していきます。

今回は文字列のコピーについて、使い方をわかりやすく解説します!

目次

文字列の代入について

文字列型のデータのコピーは数値型のデータのように「=」記号を使って代入コピーしようとしても、意図通りになりません。

配列の場合は代入することができません。ポインタの場合はアドレス先をコピーすることになります。

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

#include <stdio.h>
 
int main(void) {
    char str1[16] = "Hello World!";
    char str2[16];
    
    /* 配列の代入は不可
    str2 = str1;
    */
    
    char *ptr1, *ptr2;
    ptr1 = str1; // char型ポインタにchr型配列のアドレスを代入
    
    // 文字列のアドレスのコピー(浅いコピー)
    ptr2 = ptr1;
    printf("ptr2の文字列は: %s\n", ptr2);
    printf("ptr1のアドレス: %p, ptr2のアドレス: %p\n", ptr1, ptr2);
    
    str1[0] = 'h'; 
    printf("ptr1の文字列は: %s\n", ptr1);
    printf("ptr2の文字列は: %s\n", ptr2);
    
    return 0;
}

実行結果:

ptr2の文字列は: Hello World!
ptr1のアドレス: 0x7ffce1776b50, ptr2のアドレス: 0x7ffce1776b50
ptr1の文字列は: hello World!
ptr2の文字列は: hello World!

このサンプルコードでは、まずchar型配列「str1」を「=」記号を使って「str2」に代入しようとしています。

しかし、コンパイルエラーが発生するので コメントアウトしています。

次にchar型のポインタ「ptr1」に「str1」のアドレスを代入しています。

「ptr1」のアドレスを「=」記号を使って「ptr2」に代入しています。

結果「ptr1」と「ptr2」はアドレスが同じで、「ptr2」は「ptr1」の値と同じ値を表示しています。

この場合、「ptr1」は「str1」のアドレスですので、「str1」の最初の文字を「H」から「h」に変更すると「ptr1」の表示も変わりますが、「ptr2」の表示も変わりますので注意が必要です。

strcpyの使い方について

前述の理由で文字列のコピーには「=」記号を使った代入ではなく、strcpy関数を使用するのが一般的です。

strcpy関数はヘッダーファイル「string.h」をインクルードして使用します。strcpyの第1引数にはコピー先のアドレス、第2引数にはコピー元のアドレスを記入します。

それではサンプルコードで確認していきましょう。

#include <stdio.h>
#include <string.h>
 
int main(void) {
    char str1[16] = "Hello World!";
    char str2[16];
    
    // 文字列のコピー
    strcpy(str2, str1);
    printf("str2の文字列は: %s\n", str2);
    
    return 0;
}

実行結果:

str2の文字列は: Hello World!

このサンプルコードでは文字型配列「str1」を「str2」へstrcpy関数を使ってコピーしています。

strcpyを使用する上での注意

strcpyで文字列をコピーする場合、バッファーオーバーフローについて注意する必要があります。

バッファオーバーフローのバッファとは、メモリ上に確保する領域のことを指します。

オーバーフローとは、バッファがあふれた状態を指します。メモリ上に確保されたバッファがあふれ、意図しない動作を引き起こすことがあります。

例えば、隣接したメモリのアドレスに不正に上書きするなどです。

C言語では変数で確保したバイト数以上に、値を代入することができてしまいます。

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

#include <stdio.h>
#include <string.h>
 
int main(void) {
    char str1[16] = "Hello World!";
    char str2[4];
    
    // 文字列のコピー
    strcpy(str2, str1);
    printf("str2の文字列は: %s\n", str2);
    
    return 0;
}

実行結果:

str2の文字列は: Hello World!

先ほどのサンプルコードと同じように、文字型配列「str1」を「str2」へstrcpy関数を使ってコピーしています。

ですが、str1のバイト数が16に対して、str2で確保したメモリのバイト数は4で足りていません。

C言語では確保したバイト数が足りなくてもそのまま処理してしまいます。

これが原因で意図しないメモリの書き込みが発生してしまうこともありますので、注意しましょう!

strcpy_sの使い方

Visual StudioのC++の環境でコンパイルする際には注意が必要です。

VisualC++ではstrcpy関数を使用するとコンパイルエラーが発生し、strcpy_s関数を使うようにメッセージが表示される場合があります。

strcpy_s関数を使う場合は、文字列で受け取るメモリ領域のサイズを指定する必要があります。

strcpy_sの第1引数にはコピー先のアドレス、第2引数にはコピー先のバッファサイズ、第3引数にはコピー元のアドレスを記入します。

strcpy_s(コピー先のアドレス, コピー先のバッファサイズ, コピー元のアドレス)

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

#include <stdio.h>
#include <string.h>

int main(void) {
    char str1[16] = "Hello World!";
    char str2[16];

    // 文字列のコピー
    strcpy_s(str2, 16, str1);
    printf("str2の文字列は: %s\n", str2);

    system("pause");    // 出力表示のための一時停止

    return 0;
}

実行結果:

str2の文字列は: Hello World!
続行するには何かキーを押してください . . .

文字列の使い方総まとめ

この記事では紹介しきれなかった文字列のいろいろな使い方を次の記事にまとめているので、ぜひ確認してください!

まとめ

ここでは、文字列をコピーする方法について説明しました。

「=」記号を使った代入では意図通りにコピーすることができない場合があります。

strcpy関数を使って文字列をコピーすることができるように、この記事を何度も参考にして下さいね!

この記事を書いた人

【プロフィール】
DX認定取得事業者に選定されている株式会社SAMURAIのマーケティング・コミュニケーション部が運営。「質の高いIT教育を、すべての人に」をミッションに、IT・プログラミングを学び始めた初学者の方に向け記事を執筆。
累計指導者数4万5,000名以上のプログラミングスクール「侍エンジニア」、累計登録者数1万8,000人以上のオンライン学習サービス「侍テラコヤ」で扱う教材開発のノウハウ、2013年の創業から運営で得た知見に基づき、記事の執筆だけでなく編集・監修も担当しています。
【専門分野】
IT/Web開発/AI・ロボット開発/インフラ開発/ゲーム開発/AI/Webデザイン

目次