C言語での一般的な埋め込み面接の質問-問題1

C言語での一般的な埋め込み面接の質問-問題1

序文

このブログは、主にC言語、C ++、および埋め込まれた関連する問題を含む、学習プロセス中に収集された関連知識を共有することを目的としています。調達されていない部分を引用する必要がある場合は、時間内に書面またはコメントしてください。ブログ内容の間違った部分は時間内に修正されます。運が良ければ転載できる場合は、出典をお知らせください〜ご支援ありがとうございます!

問題1:

1.キーワードstaticの役割

C言語では、staticは主に、グローバル静的変数、ローカル静的変数、および静的関数を定義するために使用されます。
グローバル静的変数:グローバルデータ領域にメモリを割り当てます。スコープは定義されたファイルにのみ表示され、ライフサイクルはプログラムが終了するまでです。
ローカル静的変数:グローバルデータ領域にメモリを割り当て、スコープは定義されたモジュールにのみ表示され、期間はプログラムが終了するまで保存されます。
静的関数:このソースファイルでのみ使用できます。他のファイルに同じ名前の関数がある場合、それらは互いに干渉しません。
C ++には、静的データメンバーまたは静的関数メンバーの定義という2つの新しい関数が追加されています。
静的データメンバーはクラス外で定義および初期化する必要があり、静的関数は非静的データメンバーにアクセスできません

2.キーワードconstの意味は何ですか

簡単な理解:読み取り専用
(1)const int a;
(2)int const a;
(3)const int * a;
(4)int * const a;
(5)int const * a const;
ここで(1)( 2))同じ効果があります。aは定数整数です。(3)aが定数整数へのポインターであることを意味します(整数は変更できませんが、ポインターは変更できます)。(4)aの意味は、整数への定数ポインターです(ポインターが指す整数は変更できますが、ポインターは変更できません)。(5)ここで、aは定数整数への定数ポインターです(ポインターが指す整数は変更できず、ポインターも変更できません)。
いくつかの重要なアドレスとデータを保護し、コードを読む人に情報を渡し、コードが意図せずに変更されるのを防ぎます
1)キーワードconstの機能は、コードを読む人に非常に役立つ情報を伝えることです
2)与えることによってオプティマイザいくつかの追加情報を使用して、キーワードconstを使用すると、よりコンパクトなコードが生成される場合があります。
3)キーワードconstを適切に使用すると、コンパイラーは、変更したくないパラメーターを自然に保護し、コードによって意図せずに変更されるのを防ぐことができます。要するに、これはバグの出現を減らすことができます

3.キーワードvolatileの意味は何ですか、そして3つの異なる例を挙げてください

回答:コンパイラーの最適化がないと、プログラムは、レジスターに保存されたバックアップを使用する代わりに、使用するたびにこの変数を再読み取りします
1)並列デバイスのハードウェア・レジスター(ステータス・レジスターなど)
2)割り込みサービスサブルーチンでアクセスされる非自動変数(非自動変数)
3)マルチスレッドアプリケーションの複数のタスクによって共有される変数

1.パラメータをconstまたはvolatileにすることはできますか?理由を説明。
volatile修飾子は、プログラムで明示的に指定されていない方法で変数値を変更できることをサプライヤに通知します。最も一般的な例は外部ポートの値です。その変更は、プログラム内の割り当てステートメントなしで変更できます。この種の変数は、volatileで変更でき、コンパイラーはそれを最適化しません。constによって変更された変数はプログラム内で変更できませんが、外部ポートの値など、プログラム外のものによって変更できます。constのみが使用されている場合、コンパイラはこれらの変数を最適化でき、volatileは問題になりません。 。
2.ポインタは揮発性ですか?理由を説明。
ポインタは通常の変数と同じであるため、プログラムに制御できない変更が加えられることがあります。一般的な例:割り込みサービスサブルーチンがバッファーへのポインターを変更する場合、そのポインターを変更するにはvolatileを使用する必要があります。

4.参照とポインタの違いは何ですか

参照は初期化する必要があり、ポインタは初期化する必要はありません。
初期化後に参照を変更することはできず、ポインタはポイントされたオブジェクトを変更できます。
null値への参照はありませんが、null値へのポインターはあります。
ポインターは、ポインター変数を介してオブジェクトを指している後、それが指している変数を間接的に操作します。プログラムでポインタを使用すると、プログラムが読みにくくなります。参照自体はターゲット変数のエイリアスであり、参照の操作はターゲット変数の操作です。

5..hヘッダーファイルでのifndef / define / endifの役割

ヘッダーファイルが繰り返し引用されないようにします。

6.メモリ内のグローバル変数とローカル変数の違い

グローバル変数は静的データ領域に格納され、ローカル変数はスタックに格納されます。
グローバル変数のライフサイクルはプログラムの実行期間全体であり、ローカル変数のライフサイクルは変数が宣言されている関数間隔です。

7.配列とリンクリストの違い

配列は固定サイズの連続メモリ間隔であり、データは連続的にのみ保存できます。
リンクリストは、連続メモリ間隔または不連続メモリ間隔にすることができます。サイズは固定されておらず、データはランダムに保存できます。

8.一般的なスタックオーバーフローの原因

1)関数呼び出しレベルが深すぎます。関数が再帰的に呼び出されると、システムは関数が呼び出されたときに生成されたシーンと変数をスタックに保存し続ける必要があります。再帰呼び出しが深すぎると、スタックがオーバーフローし、この時点で再帰を返すことができません。関数呼び出しレベルが深すぎると、スタックがこれらの呼び出しの戻りアドレスに対応できず、スタックオーバーフローが発生する可能性があります。
2)動的アプリケーションスペースは使用後に解放されません。C言語には自動ガベージコレクションメカニズムがないため、プログラムは、使用されなくなった動的アドレス空間をアクティブに解放する必要があります。要求された動的スペースはヒープスペースを使用し、動的スペースを使用してもヒープオーバーフローは発生しません。
3)アレイへのアクセスが範囲外です。C言語では、配列添え字の境界外チェックは提供されません。配列添え字アクセスがプログラムの配列範囲を超えると、操作中にメモリアクセスエラーが発生する可能性があります。
4)ポインタへの不正アクセス。ポインタが不正なアドレスを保存し、そのようなポインタが指すアドレスにアクセスすると、メモリアクセスエラーが発生します。

9. C / C ++でのメモリ割り当て

C / C ++では、メモリはスタック領域、ヒープ領域、グローバル/静的ストレージ領域、定数ストレージ領域、コード領域の5つの領域に分割されます。通常、32ビットのLinuxカーネル仮想アドレス空間は、ユーザー空間として0 3G、カーネル空間として3 4Gに分割されます。Linuxプロセスアドレス空間の分布を次の図に示します。

スタック領域(スタック):必要に応じてコンパイラによって割り当てられます。関数が実行されると、仮パラメータとローカル変数(静的に宣言された変数を除く)がスタック領域に割り当てられます。関数の実行後、メモリは自動的にリリースされます。動的メモリ割り当て
ヒープ領域(ヒープ)に属します。ストレージのプロセス中に動的に割り当てられるメモリセグメントは、プログラマーによって手動で割り当てられ、解放されます。要求されたメモリが解放されない場合、システムはプログラムの実行後に自動的にメモリを再利用します。C言語では、メモリはmallocまたはcalloc、realloc、およびfree関数を介して要求および解放されます。**動的メモリ割り当て
グローバル/静的ストレージ領域(.dataセクション)に属します:初期化されたグローバル変数(グローバル静的変数を含む)およびローカル静的変数。これらは、プログラムの実行後にシステムによって解放されます。静的メモリ割り当てに属します。
定数ストレージ領域(.rodataセクション):グローバル定数、constで変更されたグローバル変数、文字列定数が含まれ、constで変更されたローカル変数はまだスタック領域にあります。静的メモリ割り当てに属します。
コードセグメント(.textセグメント):プログラムのバイナリコードを格納します

補足:BSSセクション(シンボルによって開始されるブロック):プログラムに初期化されていないグローバル変数と0に初期化されたグローバル変数を格納します。静的メモリ割り当てに属します。
ダイナミックリンクライブラリマッピング領域:プログラムがダイナミックリンクライブラリを呼び出す場合、それはこの部分になります。この領域は、ロードされたダイナミックリンクライブラリをマップするために使用されます。
予約領域:保護され、アクセスが禁止されているメモリ内のメモリ領域。

10. switch()パラメーターのデータ型を実行できません

回答:浮動小数点(単精度浮動小数点、倍精度倍精度)、文字列タイプ(文字列)を除きます。C / C ++は、byte、char、short、int、long、bool、integerタイプ、およびenum(列挙)タイプをサポートしています。Float、double、およびstringはサポートされていません。

11.ローカル変数はグローバル変数と同じ名前を持つことができますか

回答:はい、全体がローカルでシールドされます。グローバル変数を使用するには、「::」を使用する必要があります。
ローカル変数はグローバル変数と同じ名前にすることができます。関数でこの変数を参照する場合、グローバル変数の代わりに同じ名前のローカル変数が使用されます。一部のコンパイラでは、同じ名前の複数のローカル変数を同じ関数で定義できます。たとえば、同じ名前のローカル変数が2つのループ本体で定義され、そのローカル変数のスコープがそのループ本体にあります。

12.定義されたグローバル変数を参照する方法

回答:ヘッダーファイルまたはexternキーワードを使用できますヘッダーファイルメソッドを使用してヘッダーファイルで宣言されたグローバル変数を参照する場合、その変数を誤って記述したとすると、コンパイル中にエラーが報告されます。externメソッドを使用して引用する場合は、同じものを作成したと想定してください。間違い、その後、コンパイル中にエラーは報告されませんが、接続中にエラーが報告されます。

13.グローバル変数を複数の.Cファイルにインクルードできるヘッダーファイルで定義できますか?なぜですか?

回答:はい、異なるCファイルで静的形式で同じ名前のグローバル変数を宣言できます。
この変数の初期値を割り当てることができるCファイルは1つだけであり、現時点でリンクが間違っていない場合は、異なるCファイルで同じ名前のグローバル変数を宣言できます。

14.静的グローバル変数、ローカル変数、関数と通常のグローバル変数、ローカル変数、および関数の違い

静的グローバル変数のスコープ:変数が定義されているソースファイルでのみ有効です。
静的関数のスコープは通常の関数とは異なり、静的は現在のソースファイルでのみ記述および定義できます。
静的グローバル変数と通常のグローバル変数の違い:静的グローバル変数は、他のファイル単位で参照されないように1回だけ初期化されます。
静的ローカル変数と通常のローカル変数違い:静的ローカル変数は1回だけ初期化され、次回は前回の結果値に基づいています。
静的関数と通常の関数違い:静的関数のメモリ内のコピーは1つだけであり、通常の関数は呼び出しごとに1つのコピーを維持します。

15.事前コンパイルとは何ですか、いつ事前コンパイルが必要ですか

回答:事前コンパイルは前処理とも呼ばれ、一部のコードテキストを置き換えることです。#defineマクロ定義の置換、条件付きコンパイルなど。

16.構造体と共用体の違い

(1)構造体と共用体は、異なるデータ型の複数のメンバーで構成されています。選択された1つのメンバーのみが共用体に格納され(すべてのメンバーがアドレス空間を共有します)、構造体のすべてのメンバーが存在します(異なるメンバーの格納アドレス)。 )。
(2)ユニオンの異なるメンバーに値を割り当てると、他のメンバーが上書きされます。元のメンバー値は存在せず、構造体の異なるメンバーの割り当ては相互に影響しません。

17.#defineと比較したconstの利点は何ですか?

回答:const関数:定数の定義、関数パラメーターの変更、および関数の戻り値の変更。constによって変更されたものは、強制的な保護の対象となります。これにより、偶発的な変更を防ぎ、プログラムの堅牢性を向上させることができます。
(1)const定数にはデータ型がありますが、マクロ定数にはデータ型がありません。コンパイラーは、前者(const)に対して型安全性チェックを実行できます。defineは文字置換のみを実行し、型安全性チェックは実行せず、文字置換で予期しないエラーが発生する可能性があります。
(2)一部の統合デバッグツールは定数定数をデバッグできますが、マクロ定数はデバッグできません

18.配列とポインタの違いを簡単に説明します

回答:アレイは静的ストレージ領域(グローバルアレイなど)に作成されるか、スタックに作成されます。配列の名前は(ポイントではなく)メモリの一部に対応し、そのアドレスと容量は存続期間中変更されず、配列の内容のみを変更できます。
ポインタはいつでも任意のタイプのメモリブロックを指すことができ、より柔軟性があります。

19パラメータを含むマクロと関数の長所と短所について話し合う

1.関数が呼び出されたら、最初に実際のパラメーター式の値を見つけてから、仮パラメーターを取り込みます。パラメータ付きのマクロの使用は、単純な文字置換です。
2.マクロ置換は実行時間を消費せず、コンパイル時間のみを消費します。関数呼び出しは実行時間を消費します(ユニットの割り当て、サイトの予約、値の転送、戻り)。
3.マクロが定義されている場合、それは任意のタイプのデータにすることができます。関数内の実際のパラメーターと正式なパラメーターに対して型を定義する必要があります。2つの型要件は一貫しています。一貫性がない場合は、型変換を実行する必要があります。

20.固定メモリ位置へのアクセス(固定メモリ位置へのアクセス)

組み込みシステムでは、プログラマが特定のメモリ位置にアクセスする必要があることがよくあります。プロジェクトでは、絶対アドレスが0x67a9の整数変数の値を0xaa66に設定する必要があります。コンパイラは純粋なANSIコンパイラです。このタスクを実行するためのコードを記述します。
この質問は、絶対アドレスにアクセスするために整数をポインターにタイプキャストすることが合法であるかどうかをテストします。この問題を解決する方法は、個人のスタイルによって異なります。典型的な同様のコードは次のとおりです。int
* ptr;
ptr =(int *)0x67a9; //最初にアドレスの値を取り出し、ポインターに支払います
* ptr = 0xaa66; //次にポインターを逆参照します

総括する

近い将来、C言語、C ++、Linuxオペレーティングシステムなど、埋め込まれたインタビュー関連の質問を整理する予定です。上記の3つのパートの重要な問題に基づいて、詳細な分析と議論のために次々と更新されます。
ブログの内容が厳密でも間違っていても、時間内にコメントまたはプライベートメッセージを送ってください。できるだけ早く追加して修正します。
フィードバックもお願いします〜一緒に来てください!

おすすめ

転載: blog.csdn.net/weixin_44524004/article/details/111824585