2016-11-27 3 views
0
int main() { 
    char src[] = "santosh"; 
    char dest[0]; 
    strncpy(dest, src, 4); 
    printf("%s\n", dest); // expecting o/p "sant" but o/p was "santtosh" 
    int i = 0; 
    while (dest[i]) { 
     printf("%c", dest[i]); //expecting output "sant" but it was "santtosh" 
     i++; 
    } 

    printf("\n"); 
    i = 0; 

    while (src[i]) { 
     printf("%c", src[i]); // expecting o/p "santosh" but it was "anttosh" 
     i++; 
    } 
    return 0; 
} 

私はこのコードに問題があります。gccコンパイラを使用してコードを実行します。ここに出力があります(コメントセクション)。なぜ期待通りの行動ではないのですか?なぜstrncpy()は、dest buffが足りない場合でもソース文字列をコピーできますか?なぜ宛先バッファがゼロであってもstrncpyはソース文字列をコピーできますか?

+5

'char型のDEST [0]' < - かなり多くのあなたの全体のプログラムは、この時点では未定義の動作です。その宣言で言っていることは、 'dest'配列が0文字の* fixed *サイズであるということです。したがって、何も格納することはできず、そのアクセス(read *または* write)は未定義です。 –

+2

イギリスのポップバンド** UB40 **にちなんで名付けられました。あなたはまた 'C++'タグを削除することを検討するべきです。 –

+1

これは未定義の動作です。 Cはあなたが望む場所に書くことを可能にします。そして、もしあなたがそうしなければならないかどうかを決めるのはあなた次第です... – Charles

答えて

1

あなたのコードは未定義のビヘイビアを呼び出し、何らかの出力を生成する理由を説明しようとします。あなたが<stdio.h>、また<string.h>を含まない

  • は、ここで問題となっています。以前定義されていない関数を呼び出すことはOKではありません。未定義の動作を避けるために、適切なヘッダーファイルをインクルードします。

  • char dest[0];は、サイズが0の配列を定義します。そのようなオブジェクトにアクセスすることはできません。そのアドレスは意味がありません。 gccclangはこれを許可しますが、C標準の拡張として許可します。この定義は誤字のように見えますが、このような愚かなバグを防ぐ有用な警告を有効にするには、gcc -Wall -Wまたはclang -Weverythingを使用してください。

  • strncpy(dest, src, 4);は、destの長さが4より小さいため、未定義の動作を呼び出します。 strncpyは、ソース文字列の長さがsize引数より大きいか等しい場合に宛先配列をNULL終了しないため、の長さを持つdestの場合は、エラーが発生しやすくなります。ここで"santosh"の長さは7なので、destは、s,a,nおよびtの文字を保持しますが、ヌルターミネータは使用できません。ループのwhileは、while (dest[i])がサイズを超えてdestにアクセスするため、未定義の動作を呼び出します。 strncpy()はエラーが発生しやすく、そのセマンティクスは広く誤解されており、非常に簡単にバグを引き起こします。 この機能を使用しないでください

  • としてはdestは、現在定義されるように逆参照することができないか、char dest[4];と定義した場合であってもためwhile (dest[i])は未定義の動作を起動し、上記説明しました。

はここsnprintf()strncat()を使用して、改良版である:

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

int main(void) { 
    char src[] = "santosh"; 
    char dest[5]; 

    *dest = '\0'; 
    strncat(dest, src, 4); 
    printf("%s\n", dest);  // will output "sant" 
    for (int i = 0; dest[i]; i++) { 
     printf("%c", dest[i]); // will output "sant" too 
    } 
    printf("\n"); 

    snprintf(dest, sizeof dest, "%s", src); 
    printf("%s\n", dest);  // will output "sant" 
    for (int i = 0; dest[i]; i++) { 
     printf("%c", dest[i]); // will output "sant" again 
    } 
    printf("\n"); 

    for (int i = 0; src[i]; i++) { 
     printf("%c", src[i]); // will output "santosh" 
    } 
    printf("\n"); 

    return 0; 
} 
関連する問題