埋め込まれたc言語インタビューの質問の要約

ポインターの定義

ポインタへのポインタ、それが指すポインタは整数
int ** a;
10個のポインタの配列、ポインタは整数を指す
int * a [10]です;
ポインタは10個あります整数の配列へのポインタ
int(* a)[10]
整数パラメータを持ち、整数を返す関数へのポインタ
int * a(int){}
10個のポインタの配列。ポインタは、整数パラメータを持ち、整数を返す関数を指します
int(* a [10])(int)//この定義と同様に、分解によって実行する必要があります。最初に単一の関数ポインタint(* a)(int)を定義し、次に10個のポインタの配列int(* a [10])(int)を定義します。

キーワードstaticの目的は何ですか?


1)関数本体では、静的として宣言された変数は、関数を呼び出すプロセス中にその値を変更せずに維持します(変数は静的変数領域に格納されます)。
2)モジュール内(ただし関数外)では、静的として宣言された変数は、モジュール内で使用される関数からアクセスできますが、モジュール外の他の関数からはアクセスできません。これはローカルグローバル変数です。
3)モジュール内で、静的として宣言された関数は、このモジュール内の他の関数からのみ呼び出すことができます。つまり、この関数は、宣言されているモジュールのローカルスコープに制限されます。

キーワードconst


const inta;定数
aint consta;定数
aconst int * a;ポインタが指すコンテンツは変更できませんが、ポインタが指すアドレスは変更できます。
int * const a;ポインタが指す場所は変更できませんが、指すアドレスの内容は変更できます。
int const * consta;ポインタが指すアドレスとポインタが指すアドレスの内容は変更できません。

最初のものはaのビット3を設定し、2番目のものはaのビット3をクリアします


a | = 1 << 3
a&= 0 <<
3orBIC a、a、#0x3

符号付きおよび符号なしの番号


8.次のコードの出力は何ですか、またその理由は何ですか?
void foo(void)
{ unsigned int a = 6; int b = -20; (a + b> 6)?puts( "> 6"):puts( "<= 6"); }は6より大きい。符号付きの数値は符号なしの数値に変換されます。符号なし番号:正と負の間に違いはありません。すべてのビットは番号自体を表すために使用されます。符号付き番号:最上位ビットは数値の正と負を示すために使用され、最上位ビットは負の数値を示すために1であり、最上位ビットは正の数値を示すために0です。1.符号なし番号を符号付き番号に変換します。符号なし番号の最上位ビットが1であるかどうかを確認し、1でない場合(つまり0)、符号付き番号は符号なし番号と直接等しくなります。2。符号なし番号が最上位ビットは1で、符号なしの番号が補完され、取得された番号は符号付きの番号です。3.符号付き番号を符号なし番号に変換します。符号付き番号の最上位ビットが1であるかどうかを確認するには、1でない場合(つまり0)、符号なし番号は符号付き番号と直接等しくなります。4。署名付き番号がある場合の最上位ビットが1の場合、符号付きの数値が補完され、取得された数値は符号なしの数値であるため、6-20 = -14となります。これは、結果が符号なしの数値としてオーバーフローしたため、65536が加算され、結果が1になります。正の数65522-5は、正の数5(00000101)に対応します→すべての桁が反転します(11111010)→プラス1(11111011)












\ 0質問

void test1()
{ char string [10]; char * str1 = "0123456789"; strcpy(string、str1); } //オーバーフローと\ 0




void test2()
{ char string [10]、str1 [10]; int i; for(i = 0; i <10; i ++){ str1 [i] = 'a'; } strcpy(string、str1); } str1には\ 0ターミネータがなく、プログラムがクラッシュします。








void test3(char * str1)
{ char string [10]; if(strlen(str1)<= 10){ strcpy(string、str1); } }はstrlen(str1)<10に変更されますこのメソッドはエラーを報告しませんが、それは隠れた深刻なバグを引き起こし、メモリ内のデータを変更します。





sizeofの値とstrlenの値を計算してください。


void func(char * str)
{ sizeof(str)=?} char str [10] =“ hello”; strlen(str); 10和5




マクロ定義の問題

#include "stdafx.h"
#define SQR(X)X * X
int main(int argc、char * argv [])
{     int a = 10;     int k = 2;     int m = 1;     a / = SQR(k + m)/ SQR(k + m);     printf( "%d \ n"、a);     0を返します。} a = a /(k + m * k + m / k + m * k + m)







Cでプログラムを作成するときに、オペレーティングシステムが16ビットか32ビットかを判断するにはどうすればよいですか?sizeof()関数は使用できません。


int a = 〜0; //☆位数適用修正1if
(a> 65536)  
{   cout << "32ビット" << endl; } else {   cout << "16ビット" << endl; }





サードパーティのパラメータを使用せずに、2つのパラメータの値を交換します。


a=a+b;
b=a-b;
a=a-b;
或者
a = a^b;
b = a^b;
a= a^b;

ポインター操作

unsigned short array [] = {1,2,3,4,5,6,7};
int i = 3;
*(array + i)=?
結果は4です。

main()
{ int a [5] = {1,2,3,4,5}; int * ptr =(int *)(&a + 1); //(&a + 1)は次の1次元配列を指しますprintf ( "%d、%d"、*(a + 1)、*(ptr-1)); }解決策:int * ptr =(int *)(&a + 1);&aは、配列aの最初のストレージ領域を取得することを意味しますアドレスに加えて、配列aのストレージ領域のアドレスを示す1。これにより、ptrポインターは、アレイの最後の要素の後のストレージユニットのアドレスを指し、ptrが1減算された後、データアクセスが実行され、アクセスはptrになります。ポインタの前のストレージユニットの値。最終的な答えはすべて2、5(int *)(&a + 1)です。ポインタタイプは強制的に変換されます。







#include <filename.h>と#include "filename.h"の違いは何ですか?


<>はシステムに直接移動してトラバースします
""は最初に現在のプロジェクトのヘッダーファイルをトラバースします。存在しない場合は、システムトラバースに移動します。
<>は ""に変更できますが、 ""は<>に変更しないでください。

switch()として使用できないパラメータタイプは次のとおりです。


パラメータとして使用できるのは整数のみです

ローカル変数にグローバル変数と同じ名前を付けることはできますか?


同じ名前にすることができます。ローカル変数名はグローバル変数名を上書きします。C ++はスコープを使用して区別できます。
複数の.Cファイルに含めることができるヘッダーファイルでグローバル変数を定義できますか?どうして?
番号!しかし、それは宣言することができます。これには、強い記号と弱い記号の問題が含まれます。詳細については、次のブログを参照してください。
C言語では、関数と初期化されたグローバル変数(0への初期化を含む)は強いシンボルであり、初期化されていないグローバル変数は弱いシンボルです。
それらについては、次の3つのルールが使用されます
。①同じ名前の強いシンボルは1つしか存在できません。そうでない場合、コンパイラーは「重複定義」エラーを報告します。
②1つの強い記号と複数の弱い記号が許可されますが、定義によって強い記号が選択されます。
③同じ弱いシンボルが複数ある場合、リンカーは最大のメモリスペースを占めるシンボルを選択します。

1つの文は、xが2の累乗であるかどうかの判断を実現します。


if(x&(x-1)== 0)
    printf( "は2の累乗です");
  else printf( "は2の累乗ではありません");

pow(x、y)、
x sqrt(x)のy乗を計算し、浮動小数点数x
fabs(x)の平方根を見つけ、浮動小数点数xの絶対値を見つけます

char * s = "AAA";
printf( "%s"、s);
s [0] = 'B';
printf( "%s"、s);
何が問題になっていますか?


一定の領域ではコンテンツを変更できず、結果は変更されません。AAA

#define MAX 256
int main()
{ unsigned char A [MAX]、i; for(i = 0; i <MAX; i ++)A [i] = i; }




Charは1バイト、8ビットであり、表現できる最大の整数は255であるため、ここには無限のループがあります。

35.struct name1
{ char str; 短いx; int num; } struct name2 { char str; int num; 短いx; } typedef struct  {     int a;     char b [3];     短いd;     int c;  }ノード; sizeof(struct name1)= 8 sizeof(struct name2)= 12 sizeof(node)= 16




















バイトアラインメント

int main()
{ char a; char * str =&a; strcpy(str、 "hello"); printf(str); 0を返します。}






aにはメモリが割り当てられておらず、aは文字変数です。メモリは範囲外です。

アドレスおよび可変サイズの操作

unsigned char * p1;
unsigned long * p2;
p1 =(unsigned char *)0x801000;
p2 =(unsigned long *)0x810000;
p1 + 5 = 0x801005; p2 + 5 = 0x810014;
出力p1 + 5の値は801005です。、ポインタ変数が指す値文字にプラス1は、ポインタが1バイト後方に移動することを意味するため
5を加算すると、5バイト後方に移動することを意味します。したがって、ポインタ変数は長整数を指すため、入力801005 p5 +5の値は801016になります。はい、1を追加すると、ポインタが4バイト後方に移動し、5を追加すると、20バイト後方に移動します。したがって、入力810014(出力時は16進数)、10進数で810020になります。 

配列定義inta [2] [2] = { {1}、{2,3}}があり、a [0] [1]の値は0です。//
int(* ptr)()の場合、ptrは1次元配列の名前です。//関数ポインタ
ポインタは、どのような状況でも>、<、> =、<=、==の操作を実行できます。//不明であるため
、switch(c)ステートメントのcは、int、long、char、float、unsignedintタイプにすることができます。//違う。整数のみで、浮動小数点数は除外できます。
ライブラリ関数を使用せずに、等しい場合は0を返し、等しくない場合は-1を返す関数int strcmp(char * source、char * dest)を
記述します文字列がpalindromeであるかどうかを判別するために、function int fun(char * p)を記述し、palindromeである場合は1を返します。 、0を返す代わりに、エラー時に-1を返します

静的変数操作

#include <stdio.h>
int sum(int a)
{ int c = 0; static int b = 3; //静态c + = 1; b + = 2; return(a + b + c); } int main(){ int I; int a = 2; for(I = 0; I <5; I ++){ printf( "%d、"、sum(a)); } 0を返します。} 8,10,12,14,16、
















「hello」を出力できる必要があるのは134で、エラーは2です。


char * GetHellostr(void);
int main(void)
{ char * ps; ps = GetHellostr(); if(ps!= NULL){ printf(ps); } 0を返します。} (1)char * GetHellostr(void){ char * ps =“ hello”; psを返します。} (2)char * GetHellostr(void){ char a [] =“ hello”; return(char *)a; 内存已经被释放了} (3)char * GetHellostr(void){ static char a [] =“ hello”; return(char *)a; } (4)char * GetHellostr(void){ char * ps; ps = malloc(10);































if(NULL == ps)はNULLを返します。
strcpy(ps、” hello”);
psを返します。
}

文字列関数

char * strcpy(char * strDest、const char * strSrc)
{     assert(strDest!= NULL && strSrc!= NULL);     char * strTmp = strDest;     while(* strSrc!= '\ 0')     {         * strDest ++ = * strSrc ++;     }     strDest = '\ 0';     strTmpを返します。}








int strlen(const char * strSrc)
{     assert(strSrc!= NULL);     int len = 0;     while((* strSrc ++)!= '\ 0')         ++ len;     lenを返します。}





char * strcat(char * strDest、const char * strSrc)
{     assert((strDest!= NULL)&&(strSrc!= NULL));     char * strTmp = strDest;     while(* strDest!= '\ 0')         ++ strDest;     while(* strDest ++ = * strSrc ++);     * strDest ++ = '\ 0';     strDestを返します。}







ダブルポインターとポインター参照

void foo(char ** p)//双指针
{     * p = "after"; } int main(){     int * p = "befor";     foo(&p);     cout << p << endl; //後出的、     return 0; }








void foo(char *&p)//ポインタ参照
{     p = "after"; } int main(){     int * p = "befor";     foo(p);     cout << p << endl; // output     リターン0の後の場合; }








アセンブリ言語を使用する理由:


まず、アセンブリ言語の実行速度はc言語の実行速度よりも高速です。
2番目:起動コード。ブートローダーとカーネルを作成するときに、主にcpuとメモリを初期化するときに使用されます。現時点ではまだC言語で書かれた環境がない(スタックが確立されていない)ため、C言語は使用できません。

#ifndef X
#define X
...
#endif


ヘッダーファイルが繰り返し含まれてコンパイルされるのを防ぎます。

ポインタと配列の違い。


ストレージメソッドの最初の異なる配列は、保存されたメンバーコンテンツ自体です。ポインタは最初のアドレスを格納します。
2つ目は計算方法の違いです。配列名は定数であり、インクリメントまたはデクリメントすることはできませんが、ポインターは変数であり、インクリメントおよびデクリメントすることができます。
三つ目は、割り当て操作の操作です。配列は初期化できますが、割り当てステートメントを介して全体的な割り当てを行うことはできず、ポインターは別のステートメントを指すことができます。

strcpyがchar *を返すのはなぜですか


strcpy関数によって返される値は、チェーン操作を実現するための別の関数の実際のパラメーターとして使用できます。

IICの紹介:


開始信号:SCLがHighの場合、SDAはHighからLowにジャンプし、データの送信を開始します。
終了信号:SCLがハイレベルの場合、SDAはローレベルからハイレベルにジャンプし、データ送信を終了します。
応答信号:8ビットデータを受信した後、データを受信するICは、データを送信するICに特定の低レベルパルスを送信し
て、データが受信されたこと示します。CPUは、被制御ユニットに信号を送信した後、被制御ユニットが応答信号を送信するのを待ちます。応答信号
を受信した後、CPUは実際の状況に応じて信号を送信し続けるかどうかを決定します。応答信号が受信されない場合は、
被制御ユニットが故障していると判断します。

// IICはバイトを送信します
//スレーブ
回答があるかどうかを返します// 1、回答あり
// 0、回答なし
void IIC_Send_Byte(u8 txd)
{ u8 t; SDA_OUT(); IIC_SCL = 0; //クロックを下げますデータ送信開始するfor(t = 0; t <8; t ++){ IIC_SDA =(txd&0x80)>> 7; txd << = 1; delay_us(2); // TEA5767の場合、これら3つの遅延が必要ですIIC_SCL = 1; delay_us(2); IIC_SCL = 0; delay_us(2); } } // 1バイトを読み取り、ack = 1の場合、ACKを送信、ack = 0、nACKを送信u8 IIC_Read_Byte(unsigned char ack){ unsigned char i、receive = 0; SDA_IN(); // SDAが入力として設定されますfor(i = 0; i <8; i ++){ IIC_SCL = 0; delay_us(2); IIC_SCL = 1; receive << = 1; if (READ_SDA)receive ++;























delay_us(1);
}
if(!ack)IIC_NAck(); // nACKを送信
elseIIC_Ack(); // ACKを送信returnreceive
;
}

おすすめ

転載: blog.csdn.net/qq_38531460/article/details/103326672