2016-04-15 18 views
1

同じprintf命令のitoa(N,STR,2)atoi(STR)の呼び出しが正しく機能しないコードサンプルを示します。同じprintf命令のitoa()とatoi()が正しく機能しない

#include <stdio.h> 
#include <stdlib.h> 

main() 
{ 
    int N; char STR[50]; 
    do 
    { 
    printf("Give a number : "); 
    scanf("%d",&N); 
    printf("--------------------------------------\n"); 
    printf("Your given number is = %d\n", N); 
    printf("N in Binary = %s\t Binary String of N is = %d\n", itoa(N,STR,2), atoi(STR)); 
    printf("N in Binary = %s\n", itoa(N,STR,2)); 
    printf("Binary String of N is = %d \n", atoi(STR)); 
    printf("N in Binary = %s\t Binary String of N is = %d\n", itoa(N,STR,2), atoi(STR)); 
    } 
    while(N); 
    return 0; 
} 

問題は何ですか?

Give a number : 12 
-------------------------------------- 
Your given number is = 12 
N in Binary = 1100  Binary String of N is = 0 
N in Binary = 1100 
Binary String of N is = 1100 
N in Binary = 1100  Binary String of N is = 1100 
Give a number : 
+2

ヒント:itoa() 'を実行し、代わりに' snprintf() 'を使用してください。それは少なくとも携帯用です。 – DevNull

+0

@DevNull ack、snprintfはバイナリをサポートしていません –

答えて

3

printf()の引数が評価を取得する順番が定義されていない:ライン12と15は同じ結果が得られますが、次のように結果があったと予想されます。

は、だから、私は、この第一printf()

printf("N in Binary = %s\t Binary String of N is = %d\n", itoa(N,STR,2), atoi(STR)); 

かもしれない上述したものに副作用として

printf("N in Binary = %s\t ", itoa(N,STR,2)); 
printf("Binary String of N is = %d\n", atoi(STR)); 

にこのラインを離れて

printf("N in Binary = %s\t Binary String of N is = %d\n", itoa(N,STR,2), atoi(STR)); 

を壊したく場合であっても、未定義の動作を呼び出し、その後STRが使用されているので、この引数

... atoi(STR)); 

itoa(N,STR,2)がまだ呼び出されていなかったとして、初期化されていない(まだ)、第一に評価されます。あなたは

printf("N in Binary = %s\t Binary String of N is = %d\n", itoa(N,STR,2), atoi(STR)); 

を書くとき

+0

ありがとうございます。問題は、12行目が期待通りに正しい結果を出していないことです。 –

+1

@LiveFreeorDieHard:1番目の 'atoi'が' itoa() 'と呼ばれることがあるためです。 15行目は 'STR 'が' itoa() 'への前回の呼び出しから既に/まだ初期化されているので動作するようです。 – alk

+0

文字列STR [50]を 'char STR [50] =" 42 ";'に変更するには(プロンプトで '42 'を入力しないでください)。 – alk

6

あなたはprintfの部分項は、左から右に評価されていることを想定しているようです。 C標準では、関数の引数の評価順序は指定されていません。したがって、未定義の動作の古典的なケースがあります。

も ​​- あなたは本当にそれが最近の標準に準拠するためにmain

int main(void) 

として宣言する必要があります。

+0

多くのありがとうですが、 最初に、それがあなたの言ったとおりであれば、本当にC言語の大きなバグでしょう。 Cのマニュアルや書籍に記載されています 第2に、私は通常printfでfuctionを呼び出すと思いますが、このような混乱を見るのは初めてのことです –

+2

コンパイラは関数の引数の順序を自由に決めることが重要ですこれは、コンパイラの最適化を可能にするものの1つです。一般的な経験則として、variabを変更するもの(i ++など)を使用しないでくださいこれらの変数がまったく同じ表現の他の場所で使用されている場合は、副作用として扱われます。あなたが間違っていると思われるかもしれないので、表現の途中で副作用が起こるときを正確に推測しようとしないでください。 –

+5

@LiveFreeorDieHard正しいことを学ぶためにここにいるので、この答えを聞いてください。必要に応じて 'printf'の呼び出しの中で関数を呼び出すことができます。これは必ずしも問題ではありませんが、いくつかの関数を呼び出すと、左から右の関数に依存することは絶対にできません。これが混乱する可能性があることは事実ですが、Cの本では必ずしもうまくカバーされているとは言えません。最初は気付かなかったことは驚くことではありません。 –

-1

最後に、@ John Colemanと@Steve Summitの回答とコメントが非常に役に立ちます。

これは混乱させる可能性があり、Cの本では必ずしもうまくカバーされないことは事実ですが、そのような混乱はコンパイラの最適化を可能にします。

したがって、関数を呼び出すこと、または同じ呼び出しで依存する識別子をprintfまたは他の関数に使用しないことが好ましいという結論になります。

関連する問題