12興味深いことに、C言語のインタビューの質問

1.gets()関数

Q:質問に次のコードを見つけてください:

  1. #含める
  2. int型メイン(無効)
  3. {
  4. チャーバフ[10]。
  5. memset(バフ、0、はsizeof(バフ))。
  6. (バフ)を取得します。
  7. printf(バフ "\ Nバッファが入力は[%S]の\ nです")。
  8. 0を返します。
  9. }

:問題は、()関数を使用して、上記のコードが取得することであり、この関数は、バッファオーバーフローにつながる可能性が、標準入力からそのキャッシュ・ボリューム・コピーをチェックせずに文字列をとります。()の代わりに標準関数のfgetsを使用することをお勧めします。

C言語の面接の質問の本拠地

2.strcpy()関数

Q:ここでは、単純なパスワード保護は、あなたがそれを解読するためのパスワードを知ることができない場合には、ですか?

  1. #含める
  2. (int型ARGC、チャー*のARGV [])INT主
  3. {
  4. INTフラグ= 0。
  5. チャーのpasswd [10]。
  6. memset(passwdを、0、はsizeof(passwdファイル))。
  7. strcpyの(passwdを、ARGV [1])。
  8. (0 ==のstrcmp( "LinuxGeek" は、passwd))の場合
  9. {
  10. フラグ= 1。
  11. }
  12. IF(フラグ)
  13. {
  14. printf( "\ nはパスワードひび割れ\ nを");
  15. }
  16. {
  17. printf( "\ nは誤ったpasswdの\ nを");
  18. }
  19. 0を返します。
  20. }

:キーがブレークのstrcpy()関数の脆弱性を使用して暗号化をクラックすることです。ユーザーがキャッシュランダムなパスワードに「passwdのを」入力し、事前に確認していないときに「passwdの」容量が十分です。ユーザーが入力した場合、十分な原因のバッファオーバーフローやメモリの長い「パスワード」を書き換える「フラグ」変数デフォルト位置は、フラグの検証ビットがゼロとなっている、パスワードが検証できない場合でも、存在しているので、それはすることができますデータを保護するために得ます。例えば:

  1. $ ./Psswd aaaaaaaaaaaaa
  2. パスワードのひび割れ

上記のコードは正しくありませんが、我々はまだ、パスワードのセキュリティを回避するためにバッファオーバーフローすることができます。

このような問題を回避するために、strncpyを()関数を使用することをお勧めします。

著者注:最近、コンパイラが内部で可能スタックオーバーフローを検出しますので、これはスタックメモリのスタックオーバーフローが発生することは困難変数です。デフォルトでは、私のgccのでは、このようなものですので、私は上記のスキームを達成するために、コンパイラコマンド「-fno-スタックプロテクター」を使用する必要がありました。

3.main()の戻り値の型

Q:次のコードは、それをコンパイルすることができますか?もしそうなら、どのようなそれは潜在的な問題をするのでしょうか?

  1. #含める
  2. 無効メイン(無効)
  3. {
  4. CHAR *のPtr =(チャー*)マロック(10)。
  5. もし(NULL == PTR)
  6. {
  7. printf( "\ nはmalloc関数に失敗しました\ n");
  8. 返します。
  9. }
  10. {
  11. //何らかの処理を実行します。
  12. 無料(PTR);
  13. }
  14. 返します。
  15. }

:main()メソッドの戻り型なので、ほとんどのコンパイラでのエラーコードは、警告として扱われます。main()の戻り値の型は「INT」の代わりに「無効」にする必要があります。そのため、「INT」の戻り値の型は、状態のプログラムに戻ります。これは、プログラムの成功実行に依存が実行されているように、プログラムは、スクリプトの一部である場合は特に、非常に重要です。

4.メモリリーク

Q:次のコードは、メモリがそれをリークする原因は?

  1. #含める
  2. 無効メイン(無効)
  3. {
  4. CHAR *のPtr =(チャー*)マロック(10)。
  5. もし(NULL == PTR)
  6. {
  7. printf( "\ nはmalloc関数に失敗しました\ n");
  8. 返します。
  9. }
  10. {
  11. //何らかの処理を実行します。
  12. }
  13. 返します。
  14. }

:上記のコードが、「PTR」メモリの解放に割り当てられていないが、プログラムの終了時にメモリリークが発生することはありません。プログラムの終了時に、このプログラムは、すべてのメモリを自動的に処分される割り当てます。しかし、中に「whileループ」で上記のコードならば、それは深刻なメモリリークの問題につながります!

ヒント:メモリについての詳細をお知りになりたい場合は、知識とメモリリーク検出ツールをリークし、あなたはValgrindの上の私たちの記事を見てみることができます。

5.free()関数

Q:次のプログラムは、「シマウマ」はないが、ユーザの入力「凍結」するときに問題を起こし、なぜでしょうか?

  1. #含める
  2. (int型ARGC、チャー*のARGV [])INT主
  3. {
  4. CHAR *のPtr =(チャー*)マロック(10)。
  5. もし(NULL == PTR)
  6. {
  7. printf( "\ nはmalloc関数に失敗しました\ n");
  8. -1を返します。
  9. }
  10. それ以外の場合(ARGC == 1)
  11. {
  12. printf( "\ n個使用\ nを");
  13. }
  14. {
  15. memset(PTR、0、10);
  16. strncpyを(PTR、ARGV [1]、9)。
  17. しばらく(* PTR!= 'Z')
  18. {
  19. もし(* ptrが== '')
  20. ブレーク;
  21. ++ PTR;
  22. }
  23. もし(* ptrが== 'Z')
  24. {
  25. printf( "\ n個の文字列が 'Z' \ nは含まれています");
  26. //いくつかのより多くの処理を実行します。
  27. }
  28. 無料(PTR);
  29. }
  30. 0を返します。
  31. }

:ここでの問題は、ループが「PTR」(「PTR」を増やすことで)保存されている間のコードはアドレスを変更するということです。サイクルは、()の実行前に終了するため、変数解放するために渡されている間、入力「シマウマ」は、malloc関数()のアドレスに渡された場合。「フリーズ」、「PTR」格納されたアドレスは、whileループで変更されたときしかし、このように間違ったアドレスが、それはSEG-障害やクラッシュにつながった()解放するために渡されてしまいます。

6. _exit終了

Q:次のコードでは、atexitを()が呼び出され、なぜされていませんか?

  1. #含める
  2. 空FUNC(無効)
  3. {
  4. printf( "\ nのと呼ばれる\ n個のクリーンアップ機能");
  5. 返します。
  6. }
  7. int型メイン(無効)
  8. {
  9. int型私= 0;
  10. atexit(FUNC)。
  11. 用(;私は<0xFFFFFFの、私は++);
  12. _exit(0)。
  13. }

これは、使用_exit()関数であるため、機能は、清掃などのatexit()関数を呼び出すことはありませんされています。atexitをした場合()の出口()、またはそれに関連する「リターン」を使用する必要があります。#P#12 C-プレーン興味深い質問パート2#電子の#

7.void *およびCの構造

Q:あなたはそれが(整数)の引数のいずれかのタイプを受け入れ、結果interger機能を返すことができますをデザインすることはできますか?

A:以下の:

  1. int型のFUNC(void *型のPTR)

このパラメータは、この関数は構造によって呼び出される関数、より多くの場合、この構造は、パラメータを渡す必要で充填することができます。

8. * ++および操作

Q:何が出力されます、次のアクション?なぜ?

  1. #含める
  2. int型メイン(無効)
  3. {
  4. するchar * ptrは= "Linuxの";
  5. printf( "\ n [%C]の\ n"、* PTR ++)。
  6. printf( "\ n [%のC]の\ n"、* PTR)。
  7. 0を返します。
  8. }

A:出力は次のようになります。

  1. [L]
  2. [私]

そのため、 "+" と "*" の優先順位として、いわゆる "* ptrに++" 同等 "*(PTR ++)"。すなわち、第一の実施PTR ++でなければなりません、とだけにして* ptrは、その演算の結果が「L」です。2番目の結果は、「I」です。

9. Q:修正コード(または読み出し専用コード)

Q:次のコードセグメントが間違っている、あなたはあなたに指摘することができますか?

  1. #含める
  2. int型メイン(無効)
  3. {
  4. するchar * ptrは= "Linuxの";
  5. * PTR = 'T';
  6. printf( "\ n [%S]の\ n"、PTR)。
  7. 0を返します。
  8. }

:これは、メモリのコードセグメント(読み取り専用コード)の「Linux」の最初の文字の* PTR、変化=「T」によって、ためです。この操作は、このようにワンセグ障害またはクラッシュを与え、無効です。

10.彼の名前の進路を変更

Q:あなたは、実行時に、それを自分の名前を変更するには、プロセスを書くことができますか?

次のコードを参照してください。

  1. #含める
  2. (int型ARGC、チャー*のARGV [])INT主
  3. {
  4. int型私= 0;
  5. チャーバフ[100]。
  6. memset(バフ、0、はsizeof(バフ))。
  7. strncpyを(バフ、ARGV [0]、はsizeof(バフ))。
  8. memsetの(ARGV [0]、0、strlenを(バフ))。
  9. strncpy(ARGV [0]、 "NewNameパラメータ"、7)。
  10. //待機をシミュレートします。プロセスをチェック
  11. //この時点で名前。
  12. 用(;私は<0xffffffffの、私は++);
  13. 0を返します。
  14. }

11.ローカル変数のアドレスを返します。

Q:次のコードは、問題がありますか?もしそうなら、どのように修正するには?

  1. #含める
  2. int型*株式会社(int型のval)
  3. {
  4. int型、A =ヴァル;
  5. ++;
  6. 返します&;
  7. }
  8. int型メイン(無効)
  9. {
  10. = 10 INT。
  11. int型*ヴァル= INC(A);
  12. printf(*ヴァル "\ nはインクリメントされた値は、[%のD] \ nと等しいです")。
  13. 0を返します。
  14. }

:上記の手順は時々正しく実行することができますが、中に「()INC」の重大な欠陥がありますが。この機能は、ローカル変数のアドレスを返します。INCの終わりに、悪い結果が発生したローカル変数を使用するように、ローカル変数のライフサイクルは、「INC()」ライフサイクルであるためです。後にも格納されたアドレス値を変更することができるように、これは、main()の変数のアドレス「」を回避することができます。

12のprintfのプロセスパラメータは、()

Q:次のコードの出力は何ですか?

  1. #含める
  2. int型メイン(無効)
  3. {
  4. = 10 int型、B = 20、C = 30。
  5. printf( "\ n%D ..%D ..%D \ n" は、A + B + C、(B = B * 2)、(C = C * 2))。
  6. 0を返します。
  7. }

A:出力は次のようになります。

  1. 110..40..60

デフォルトのC言語関数のパラメータは、右から左に処理された出力があるときに右に残っているためです。

C言語の面接の質問の本拠地

おすすめ

転載: www.cnblogs.com/miansheng/p/11297114.html