web-dev-qa-db-ja.com

C ++:strcpy関数はnullをコピーしますか?

特にstrcpy文字列操作関数を使用しながら、この小さなプログラムを実行しました。

char s1[8]="Hellopo";
char s2[4]="sup";
strcpy(s1,s2);
cout<<s1<<endl;

S1を出力したときは、実際には「sup」と出力しただけです。 「suplopo」を印刷することを期待していました。

それから私はこれをしました:

cout<<s1+4 << endl;

「opo」を出力しました。

そして、この出力:cout<<s1+3<<endl;は何もありませんでした

それについて少し考えた後。

私はこの結論に達しました。 C++は、文字列がnullターミネータに到達すると出力を停止するためです。したがって、ヌルはstrcpy関数にコピーされている必要があります。次の文字列になります:

s-u-p-\ 0-o-p-o-\ 0;

これが正しいかどうか教えてください。そして私がそうでない場合は私を修正してください。

また、提供する情報が他にもある場合は、ぜひお知らせください。

22

あなたの推論は正しく、まともな manual

strcpy()関数は、終端のnullバイト('\0')を含め、srcが指す文字列をdestが指すバッファーにコピーします。

38
Kerrek SB

あなたは正しいです。最初に期待した効果については、strncopyを使用します。 strncopyは、コピーされる文字列の正しい長さを指定する限り、nullターミネーターをコピーします。

2
steveg89

終了文字のコピーに関するあなたの推論は正しいです。 C++標準(これは言語の最終的な仕様です)はこの問題に関してCに従います(たとえば、C++ 14はC99に従い、C++ 17はC11に従います)。

C11標準では、これについてstrcpyについて述べています。

7.24.2.3 strcpy関数

概要:

_#include <string.h>_
char *strcpy(char * restrict s1, const char * restrict s2);

説明:

strcpy関数は、_s2_が指す文字列(終端のnull文字を含む)を_s1_が指す配列にコピーします。重複するオブジェクト間でコピーが行われた場合の動作は未定義です。

戻り値:

strcpy関数は、_s1_の値を返します。

文字列の最初の3文字を置き換えるだけの場合は、memcpy()を使用して特定のバイト数をコピーできます。

_memcpy(s1, s2, strlen(s2));
_

これは、それらのバイトのみをコピーし、それ以上はコピーしないことに注意してください。 _s1_が少なくとも_s2_の長さの文字列でない場合は、正常に終了する可能性は低いです:-)


そして、あなたのコメントを覚えておいてください "...結果は次の文字列になります: sup\0opo\0」.

つまり、文字列ではありませんではありません。 Cの文字列(およびC++のレガシー文字列)は、first_\0_ターミネーターまでの一連の文字として定義されます。

元の(現在は2番目の)_\0_までの一連の文字を使用することもできますが、stringは実際にはそれよりも短いです。これは少し見た目がよいかもしれませんが、定義を理解することが重要です。

2
paxdiablo

strcpyのmanページから:

strcpy()関数は、終端のnullバイト('\0')を含め、srcが指す文字列をdestが指すバッファーにコピーします。文字列は重複してはならず、コピー先の文字列destは、コピーを受け取るのに十分な大きさである必要があります。

1
xbonez

これは正しいです。

http://pubs.opengroup.org/onlinepubs/009695399/functions/strcpy.html

Strcpy()関数は、s2が指す文字列(終端のnullバイトを含む)をs1が指す配列にコピーします。

1
Dave Rager

はい、これは正しいです。 strcpyにはnullターミネータが含まれます。文字列を新しいメモリブロックにコピーする場合は、デフォルトでnullで終了することが重要です。この場合、strncpyがあなたの狙いかもしれません。

また、コードをテストするだけだったのはわかっていますが、この日と文字列で+ Xオフセットを使用する年齢には注意が必要です。

1
sradforth

はい、あなたの推論は正しいですし、4番目の文字「s1 [3]」を次のように整数として明示的に型キャストした場合:

cout <<(int)s1 [3];

ASCII NULL文字の値である出力として、 "0"を取得することになります。

0
NovicE_Neo