2016-11-23 4 views
2

文字列をdest文字列にコピーしようとしています。私が次のプログラムをコンパイルすると:メモセットと文字

#include <stdio.h> 

int main(void) { 
    char dest[6]; 
    char source[6]; 

    strcpy(dest,source); 

    while (*dest) { printf("%c",*dest++); } 
    while (*source) {printf("%c",*source++); } 

    return 0; 
} 

実行時エラーが発生します。私はそれがが出会いまでに出くわすまでコピーするからだと思う。しかし、null文字に遭遇せず、実行時エラーが発生するまでバッファーからのコピーを続けました。次のようにこの問題を解決するために、私は、コードを変更:

#include <stdio.h> 

int main(void) { 
    char dest[6]; 
    char source[6]; 


    memset(dest, '\0', 6*sizeof(dest)); //trying to set dest to '/0' 
    strcpy(dest,source); 

    while (*dest) { printf("%c",*dest++); } 
    while (*source) {printf("%c",*source++); } 

    return 0; 
} 

は、私は、次のエラーを取得:

prog.c:11:38: error: lvalue required as increment operand

while (*dest) { printf("%c",*dest++); } 
           ^

prog.c:11:38: error: lvalue required as increment operand

while (*dest) { printf("%c",*source++); } 
            ^

これはなぜ起こるのでしょうか?

+3

第1のプログラムは、第2のプログラムと同じ理由で(http://ideone.com/2Zy1hx)コンパイルできません。それがあなたが使っていたソースだと確信していますか? – templatetypedef

+1

また、配列に++を適用することはできません。 :-) – templatetypedef

+3

'dest'が配列の場合、' dest ++ 'は正当なCコードではありません。 – templatetypedef

答えて

4

それはあなたが別の文字配列にそれをコピーしようとしている場合は、ゼロを終了するものとソース配列であります標準のC関数strcpyを使用します。それは、アレイに割り当てられたメモリが上書きされるためので、代わりにこの文

memset(dest, '\0', 6*sizeof(dest)); 

のあなたは、少なくともこの文は間違っているがさえ

memset(source, '\0', 6*sizeof(source)); 
     ^^^^^^    ^^^^^^^ 

を記述する必要があります。それは

char source[6]; 

このように配列宣言から続いているようsizeof(source)はあなたのようなどちらか

が実際に書くことが十分にあった記述する必要があり、すでに6バイトに等しい

char source[6] = { '\0' }; 

char source[6] = ""; 

など

char source[6]; 
source[0] = '\0'; 

アレイは変更不可能な左辺値です。したがって、あなたは、たとえば代わり​​にこのステートメントの次のよう

while (*dest) { printf("%c",*dest++); } 

を記述しないことがありますが

for (char *p = dest; *p; ++p) { printf("%c", *p); } 

を書くことができ、配列が空の文字列が含まれているため、何も出力されないことを考慮してください。いくつかの空の文字列リテラルでソース配列を初期化することができます。

+0

この行は、 'memset(source、 '\ 0'、6 * sizeof(source));'が正しくありません。 'sizeof(source)'は6で6 * 6は36なので、最初の6が配列境界の終わりを越えた後で36バイトがクリアされます。結果は未定義の動作であり、seg faultイベントにつながる可能性があります。 '6 *'の削除を提案する – user3629249

+0

@ user3629249あなたのコメントを書く前に投稿全文を読んだのですか?:) –

+0

はい、投稿全体とあなたの答えを読みました。あなたの答えは、OPの掲示されたコードの問題の1つを伝播しています。 – user3629249

-1

strcpyは安全な機能ではありません。strncpyを使用することをお勧めします。

このエラーは、配列をインクリメントしようとした場合に発生します。これは、値(つまり、定数の場合は、記号=の左側に置くことはできません)です。

配列を反復処理するための一般的なアプローチはそうのようなポインタを使用することです。手始めに

char *p = dest; 
while (*p) { printf("%c",*p++); } 
+0

下垂を説明するのは気にかかりますか? –

+0

私はdownvoteしませんでしたが、 'strncpy'は' strcpy'の単なる安全版ではありません。歴史的な理由から実際には非常に驚くべきことがいくつかあります。したがって、多くの場合、おそらくあなたが望むものではありません。 –

+0

私が知る限り、strncpyの欠点は、最大サイズに達した場合に '\ 0'バイトを追加しないことですが、初期化されていないデータを使用していて、ポインタとメモリを試してみてください。 –

1

次のコードはきれいにコンパイルし、目的の操作を実行します。

投稿コードとこれとの相違点についてはコメントがあります。

#include <stdio.h> // printf() 
#include <string.h> // strcpy() 

int main(void) 
{ 
    char dest[6]; // declared, containing garbage 
    char source[6] = "12345"; // declared, containing the string "12345\0" 

    strcpy(dest,source); 
    // now both arrays contain the string "12345\0" 

    // best to use a 'for()' statement for indexing through an array 
    for(size_t i=0; dest[i]; i++) { printf("%c", dest[i]); } 
    printf("\n"); // output the buffered data to the terminal 
    for(size_t i=0; source[i]; i++) { printf("%c", source[i]);} 
    printf("\n"); // output the buffered data to the terminal 

    // note, the following lines contain a precedence problem in 
    // the increment expressions and 
    // the address of an array declaration cannot be incremented 
    //while (*dest) { printf("%c",*dest++); } 
    //while (*source) {printf("%c",*source++); } 

    //return 0;// with modern C compilers, 
      // this line is not necessary in a 'main()' function 
      // when returning 0 
} // end function: main