3

みんなへの最初のハロー、ここに最初の投稿。

今日、私はこのコードが正しいかどうか疑問に思いました。それはマイクロコントローラーの友人によって以前に書かれたものであり、私はもう彼に尋ねる機会がありません。

プログラムは正しく動作しますが、運が良かったかどうかを実際に判断することはできません(プログラミングで運が良かったとは思わないでください)。この投稿のタイトルが正しいかどうかさえわかりません。誤解を招く可能性がある場合は申し訳ありません。コード:

char  *textStatusErrorMessage( unsigned int codeStatus )
{
    switch ( codeStatus ) {

    case STATUS_1:
        return ( (char  *) " Status: 1 " );
        break;     
    case STATUS_2:
        return ( (char  *) " Status: 2 " );
        break;      
    default:
        sprintf( tmpBuf, " UNKNOWN STATUS   %03d ", codeStatus );
        return ( (char  *) tmpBuf ); //tmpBuf is global
        break;
    }
}

もっと正確に言えば、この構文は私にはちょっとわかりにくいです。

return ( (char  *) " Status: 1 " );

何のchar*を返しますか?保存された「ステータス:1」文字列はどこにありますか?ヒープ/スタック???

実装されているため、文字列は関数のスコープ内にあり、returnステートメントを使用して関数を終了した後、関数自体によって返されるポインターに何が書き込まれるかを制御できないと想定しています。

私の見方からすると、可能な文字列オプションが異なるグローバル配列があり、CASEによって選択された正しい配列へのポインタが返されます。したがって、私が返すポインタは、明確に定義されたメモリ領域へのポインタであることがわかります。

それで、このコードは間違っているかどうか?最も正しい解決策はどれですか?

ありがとうDAN

4

2 に答える 2

6

理論的には、このコードは有効です。文字列リテラル (例: " Status: 1 ") の型はchar[]であり、寿命はプログラム全体の寿命と同じです。

ただし、いくつかの問題があります。

  1. 文字列リテラルの場合、返された文字列を変更しようとすると、未定義の動作が発生します。実際、この関数はconst char *代わりに a を返す必要があります。

  2. tmpBufが宣言されている場所や、書き込まれるデータを保持するのに十分なメモリを指しているかどうかは明らかではありません。

  3. は1 つ しかないtmpBufため、この関数が呼び出されるたびtmpBufに上書きされます。これにより、追跡が困難なバグが発生する可能性があります。

  4. キャストは不要です。

于 2013-01-28T15:50:36.040 に答える
3

それは何を返しますchar *か?

char[]文字列リテラルが aにキャストされchar*ます。自動的に there に変換されるため、これは必要ありませんchar*

「Status: 1」文字列はどこに保存されていますか? ヒープ/スタック???

通常、文字列リテラルはプログラムのデータ (またはrodata) セグメントに格納されます。しかし、それは重要ではありません。関連するのは、文字列リテラルには静的な保存期間があるため、コードは有効であり、返されたポインターは、関数が返された後に存在しないローカル変数を指していないということです。

于 2013-01-28T15:51:07.413 に答える