memcpy関数の使用方法と注意点

このQ&Aのポイント
  • memcpy関数を使用して文字列の一部を置換する場合、先頭アドレスを渡さなければならないことに注意が必要です。
  • ポインタや配列の先頭アドレス以外はmemcpy関数に渡すことができません。
  • 動作停止する場合は、str1の先頭アドレスを正しく指定していない可能性があります。関数を作成することで解決することもできます。
回答を見る
  • ベストアンサー

memcpy関数について

c言語のmemcpy関数についてなのですが、 文字列の一部を置換する場合にmemcpyを使用したいのですが、使用してやってみたところ動作停止します。memcpyは先頭アドレスを渡さないと動作しないのでしょうか。 また、memcpy関数以外でも、ポインタや配列の先頭アドレスしか渡せないのでしょうか? 例えば、 memcpy(str1,str2,5); ならば、動作しますが、 str1++; memcpy(str1,str2,4); では、動作停止しました。 もし、memcpy関数は先頭アドレスじゃないと動作しない場合は関数を作って出来るのですが…。 もし、不足しているもの等あれば、補足で追加するので回答をお願いします。

  • RJMS
  • お礼率70% (58/82)

質問者が選んだベストアンサー

  • ベストアンサー
  • kawais070
  • ベストアンサー率52% (2242/4282)
回答No.3

回答No.1のソースは、今どきのコンパイラでは動作しませんね。 理由は↓ https://www.jpcert.or.jp/sc-rules/c-str30-c.html 今どきのコンパイラでも動作するようにしました。 char buff[256]; char buff2[256]; char *str1=buff; char *str2=buff2; strncpy(str1, "abcdef", 7); strncpy(str2, "123456", 7); str1++; memcpy(str1,str2,4); printf("str1=%s",str1);

RJMS
質問者

お礼

回答ありがとうございます!! 動作確認したら動作したのでありがとございました

その他の回答 (2)

  • kawais070
  • ベストアンサー率52% (2242/4282)
回答No.2

str1の型は何でしょうか? もし、構造体のポインタだったら、++することで、構造体のサイズ分だけポインタに加算されます。

RJMS
質問者

お礼

すみません…。型を書くのを忘れていました。 文字列の置換だったので、char型でした。 回答ありがとうございます。

  • maiko0318
  • ベストアンサー率21% (1483/6970)
回答No.1

#include<stdio.h> #include<string.h> int main(void){ char *str1="abcdefghi"; char *str2="1234567890"; str1++; memcpy(str1,str2,4); printf("str1=%s",str1); } 問題無いですね。 ソースの全体があるなら補足してください。

RJMS
質問者

お礼

すみません。回答していたソースコードを試してみたのですが、動作停止します。コンパイラの問題なんでしょうか。 開発環境は、visualstdio2013を使用しているのですが…。

関連するQ&A

  • C言語のmemcpy関数について質問します。

    C言語のmemcpy関数について質問します。 以下のプログラムを作成して実行したのですが期待した動作が行えません。 どなたか原因が分かる方がいましたらアドバイスいただければと思います。 (期待する動作) STR_Bに"aaaa"を格納したい (現在の動作) STR_Bに"aaaabbbb"が格納される。 (printfで"aaaabbbb"が表示される) (以下プログラムです) char *STR_A = "aaaabbbb"; char *STR_B; /* 初期化 */ memset(&STR_B,0x00,sizeof(STR_B)); /* 文字列コピー */ memcpy(&STR_B,&STR_A,4); /* コピーした文字の表示 */ printf("STR_B = %s\n",STR_B);

  • 関数へのポインタ渡しでの配列の初期化について

    はじめまして、C言語の基本的な質問をさせてください。 C言語で、外部関数へポインタで引数を渡す場合に、 関数に渡されるのはアドレスですよね? で、渡された関数側でそのポインタの配列の初期化を するときにはアドレスだけの情報だと、要素数がいくつ あるか分からず、領域の破壊をしてしまいそうな気が するのですが?いかがでしょうか? また、関数かなんかで、配列の要素数が分かる関数が あったような気がするのですが、それもアドレスだけ でわかるのでしょうか?

  • malloc領域から関数ポインタ型で呼び出し

    現在C言語で,関数ポインタ型による関数の呼び出しを勉強しています. print()という関数は受け取った文字列を表示するだけの関数ですが, これを通常の関数ポインタを用いて実行したのがmain内の(*mem)("FROM POINTER.");です. これに対して後半は,mallocで確保した領域にmemcpyでprint()をコピーし, (*mem)("FROM COPIED AREA.");で実行しています. 実行環境は以下の通りです. OS:Windows7 Personal 32bit CPU:Intel Core i5 M430 統合開発環境:Visual C++ 2010 Express Edition コンパイルには成功しています. 実行すると"FROM POINTER."は表示されるのですが, "FROM COPIED AREA."は表示されず,プログラムが動作を停止してしまいます. mem = (void (*)(char*))tmp;までは実行できているようですが, (*mem)("FROM COPIED AREA.");の実行の時点で停止しているようです. またコマンドプロンプトからBorland C++ 5.5.1でコンパイルしても, 同じように動作が停止してしまいます. ただし同じプログラムでも,Cygwinからgccでコンパイルすると, 意図した通りの挙動となっていることを確認しています. コンパイラの違いによるものなのか, UNIXとWindowsの違いによるものなのか判断できずにいます. (もしくはライブラリのmalloc,memcpy辺りの実装法の違いでしょうか?) どなたかご存知でしょうか. ----------------------------------------- #include<stdio.h> #include<stdlib.h> #include<string.h> #define SIZE 512 void print(char* str){ printf("%s\n", str); } int main(int argc, char** argv){ void (*mem)(char*); void *tmp; mem = &print; (*mem)("FROM POINTER."); tmp = malloc(SIZE); memcpy(tmp, print, SIZE); mem = (void (*)(char*))tmp; (*mem)("FROM COPIED AREA."); }

  • 「memcpy」と「strcpy」について

    C言語の初心者です。 先日、課題として以下のようなことを言われました。 「memcpyとstrcpyについて、メモリ破壊が起こるとしたら どんな場合が考えられるか、簡単にまとめて報告してみて下さい。」 と言われました。 私にはメモリ破壊というニュアンスが分からないのですが、 どちらの関数も必要以上にコピーを行ったときに 起こるメモリ破壊ということなのでしょうか? それとも、何か特別な意味があるのでしょうか? C言語に詳しい方がいましたら、是非、教えて下さい。 宜しくお願いします。

  • C言語の型と配列

    char* str[10]={"a","b"}; char* str2="c"; としたときにstr=str2とすると 型が合わないといったエラーが出ます。 でもstrって結局はポインタの配列の先頭要素のアドレスですよね。 ポインタにポインタを入れているので通るのかなと思ったんですけど、 配列で宣言するとポインタにも型がつくのでしょうか? この例だと strは char * を10個持つ配列をさすポインタ  で、 str2はchar *をさすポインタ みたいなかんじです。 質問の意味がわかりにくいですが、ご指摘をいただければ補足しますので よろしくお願いします。

  • 関数の引数

    こんにちわ。 ご存知の方、ご教授してもらえないでしょうか? VB.net2005を使っているのですが 関数の引数に変数をセットして、別関数で 引数に対してデータをセットすることは可能でしょうか? C言語でいうところのポインタを引数に渡し ポインタアドレスに書き込むような処理はVB.netでは 可能なんでしょうか? 下記のような事は試したのですが、うまく出来ませんでした(。。; public sub test1() dim mojiretu as string test2( mojiretu ) msgbox(mojiretu) end sub public sub test2( str as string) str = "文字列" end sub

  • 配列で混乱しています

    c言語を勉強中のものです。文字列を配列で扱う場合とポインタで扱う場合の違いにこんらんしています。 たとえば char str[] = "hello"; str = "goodby"; のように文字列の再格納はダメですが、 char *str = "helllo"; str = "goodby" は大丈夫です。 また char[100]; scanf("%s",str) は大丈夫ですが char *str; scanf("%s",str) はいけません。この2つの違いは何によるのでしょうか? またポインタはそもそも int a; int *pa; pa = &a; のように、宣言したあとはアドレスを入れる専用のハコのように考えていたのですが、 char *str = "helllo"; str = "goodby" のようにいきなりアドレスでない文字列を代入するのも納得がいきません。誰か解説をお願いします。

  • 配列を返す

    ファイルから読み込んだ一行の文字列を読み込みカンマごとに区切って 返すというプログラムを関数化することで効率を図りたいと思います。 int main() { char buf[1000]; char *str; char *bufG; //ファイルを読み込む  while(fgets(buf,1000,fp) != NULL){//一行ずつ読む str = buf;//先頭アドレスを指す     bufG = //文字列を返す関数  ・  ・  ・ } } //文字列を返す関数 {    for(i = 0; *str != ',' && *str != '\0'; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; return bufG; } 前の質問で自動変数でこの関数を抜けたら廃棄になるというのは わかったんですが(そういう警告がでました) ここからどのようにすれば求めるプログラムになりますか? 引数とかちょとわからないので関数定義を書きませんでした。 (1)ファイルをよみこむ (2)一行ずつ読み込み文字列をbufにいれる (3)ポインタstrをbufの先頭アドレスにする (4)get_word関数にてポインタをずらしていき カンマがあればそこまでの文字列を返す (5)main関数に戻り変数に代入する (6)終端文字があるまで(4)ー(5)を繰り返す。 (7)さらに行数分繰り返す これらの一連の流れをやりたいのですが わかりません。

  • C言語:小文字を大文字に変換する関数を作成

    C言語超初心者です。学校の課題で次のような問題が出されました。 ・問題・ 次に挙げる縛りに沿い、以下の関数とメイン関数を作り、処理結果を画面に作成しなさい。 char *tst(char *str) ・strの中の文字列も小文字を大文字に変換し、変換した文字列が格納されているchar *に返す。 ・引数strの中の文字列は受け取った状態で手を加えない。 ・関数内でmalloc関数を使用し、領域を確保して大文字に変換した文字列を格納しreturnでポインタを返す。 ・malloc関数を使用する。 ---------------------------------------------------------------------------------- 大文字に変換するには while(*str != '\0') { if(*str >= 'a' && *str <= 'z') { *str -= 'a'- 'A'; } ++str; } というのは分かったのですがここから何をすするか全く分かりません。初心者なのでなるべく分かりやすく教えてもらえると有難いです。 お願いします。

  • アドレス

    char str[100]; このとき&strは配列strのアドレスだと思いますが、これは 何のアドレスですか?又strは配列の要素の先頭アドレスですが これとどう違うのでしょうか?

専門家に質問してみよう