C ++言語トラップ

プログラミング言語の明白ではないさまざまな「機能」を説明する一連の記事を作成するとよいでしょう。 第一に、「事前に準備された」という意味です。そして、第二に、それらを知ることにより、言語をよりよく理解し、何かが起こった場合、なぜ危険なのかを説明できます。 そのような構造が独自のコードで使用されていなくても、他の人のコードを解析したり、チームで作業しているときにこれらのトラップに遭遇する可能性があります。



したがって、C ++でchar



と入力します。



問題の主な原因は次のとおりです。





最初の項目の詳細。 「ネイティブ型」 byte



がないため、 char



型を使用して構築されます。 標準では、 char



signed char



およびunsigned char



タイプが3つの異なるタイプであることを明確に明確にしています。 他の整数型にはこのプロパティがありません。たとえば、 int



signed int



は同じ定義です。 ここでの追加の熊手は、char型自体が署名されているか署名されていないという事実です。これはプラットフォーム(大まかに言って、コンパイラとそのキーのセット)に依存します。 しかし同時に、とにかく、コンパイラーはそれらをすべて互いに区別する義務があります。



したがって、そのような定義:

 void foo(char c); void foo(signed char c); void foo(unsigned char c);
      
      





3つの異なる機能を発表します。 これらのタイプのさまざまなプロパティの「混合」が発生する問題は、たとえば次のコードで示すことができます。

 #include <iostream> #include <stdint.h> int main() { uint8_t b = 42; std::cout << b << std::endl; //   *,    42. }
      
      





要約:特定の状況での「バイト」整数型は、「シンボリック」な本質を明白でない結果で明示できます。



2番目のポイントに進みましょう。 Cでは、文字列を操作するための特別な型はありません。 慣例により、 char*



(またはconst char*



)ポインターがある場合、これはおそらく文字列であり、適切な関数に渡すことができると考えられています。 プレーンCでは、たとえば次のような驚くべきことが可能です。

 int main(void) { char* ptr = "hello"; //   C,     ptr[1] = 'q'; //    "abcd"[1] = '2'; //    - ,     - read-only,           return 0; }
      
      



良いニュースは、C ++ではこの「機能」が転送されなかったことです。



しかし、残りはどこにも行っていません。 たとえば、文字列リテラルはそれ自体の内部でヌル文字を許可し(たとえば、 "abc\0\123"



)、それらと連携するように設計された関数( strlen



など)はそのような文字列をサポートしません。 つまり、「すべての行はゼロで終わる非ゼロ文字のシーケンスである」という決定により、すべての行が「指定された長さを取得する」などの複雑なO(n)文字列。」



さらに、コンパイラはすべての文字列リテラルに'\0'



を自動的に追加するため、次のような結果になります。

 char str1[] = "1234"; //    5 ,   4 char str2[4] = "1234"; // ,       char str3[4] = {'1', '2', '3', '4'}; // ...   
      
      





すべてが順調に進んでいるようです。 ただし、最後の行には隠しレーキが含まれています。通常のchar*



ように見えます。つまり、 puts



strlen



などに渡すことができます。 未定義の動作を取得します。



要約すると、可能な場合は、C ++プログラムで「古い」Cスタイルの文字列を使用しないでください。



All Articles