寫出Bool、int、指針變量、float與“零值”比較的if語句
Bool型:
if(flag)、if(!flag)
int型:
if(flag == 0)、if( flag!= 0)
指針變量:
if(p == NULL)、if( p!= NULL)
float型:
const float EPSINON = 0.0001; if( (x >= -EPSINON) && (x <= EPSINON));
設(shè)置地址未為0x67a9的整型變量的值為0xaa66
int *prt;
ptr = (int *)0x67a9;
*ptr = 0xaa66;
*(int *)0x67a9 = 0xaa66;
要對絕對地址賦值,我們可以用(unsigned int*)0x10000=1234,那么要想程序跳轉(zhuǎn)到絕對地址是0x10000去執(zhí)行,應(yīng)該怎么做?
先強制轉(zhuǎn)換成函數(shù)指針:(void(*)())0x10000;
再調(diào)用它:*( ( void(*)( ) )0x10000 )();
描述一下gcc的編譯過程
gcc編譯過程分為4個階段:預(yù)處理、編譯、匯編、鏈接
預(yù)處理:進行頭文件、宏定義的替換,條件編譯,刪除注釋,還有語義和詞義的分析
編譯:將預(yù)處理后的文件編譯成匯編文件
匯編:將匯編文件轉(zhuǎn)換二進制文件
鏈接:將二進制文件鏈接成可執(zhí)行文件
#include< >和#include" "的區(qū)別
#include< >是到系統(tǒng)指定目錄下尋找文件;
#include" "是先到用戶指定的目錄下尋找文件,找不到就到系統(tǒng)指定目錄下尋找
頭文件中的ifndef/define/endif 干什么用
防止頭文件被重復(fù)引用。
有符號與無符號的區(qū)別
有符號的數(shù)據(jù),最高位為符號位,0表示正數(shù),1表示負數(shù);
無符號的數(shù)據(jù),最高位不是符號位,只是數(shù)據(jù)的一部分。
sizeof與strlen的區(qū)別
sizeof是操作符,參數(shù)可以是數(shù)據(jù)類型,也可以是變量,在編譯時就已經(jīng)計算出來sizeof的結(jié)果,計算的是數(shù)據(jù)類型占內(nèi)存的大??;
strlen是庫函數(shù),參數(shù)只能是以‘\0’結(jié)尾的字符串,需要在運行時才能計算出來,計算的是字符串的長度;
嵌入式系統(tǒng)中經(jīng)常要用到無限循環(huán),你怎么樣用C編寫死循環(huán)
while(1)
{}
for(;;)
{}
loop: ···
goto loop;
宏定義
寫一個標(biāo)準(zhǔn)宏MIN
#define MIN(x,y) ( (x)<=(y)? (x):(y) )
用預(yù)處理指令#define聲明一個常數(shù),用以表明1年中有多少秒(忽略閏年問題)
#define SEC_YEAR (365 * 24 * 60 * 60)UL
用宏定義寫出swap(x,y),即交換兩數(shù)
#define swap(x,y) x=x+y;y=x-y;x=x-y;
已知一個數(shù)組table ,用一個宏定義,求出數(shù)據(jù)的
#define LENGIH sizeof(table)/sizeof(table[0])
關(guān)鍵字
關(guān)鍵字static的作用是什么
-
修飾局部變量時,變量只執(zhí)行一次,存在于靜態(tài)存儲區(qū),不初始化內(nèi)容為0,只在當(dāng)前語句塊有效,程序結(jié)束后才釋放。
-
修飾全局變量時,變量存在于靜態(tài)存儲區(qū),不初始化內(nèi)容為0,只在當(dāng)前文件有效,程序結(jié)束后才釋放。
-
修飾函數(shù)時,該函數(shù)只能在當(dāng)前文件中使用。
static函數(shù)與普通函數(shù)的區(qū)別與好處
static修飾的函數(shù)只能在當(dāng)前文件使用;
普通函數(shù)可以被外部文件用extern調(diào)用;
用static修飾函數(shù)的好處是:
-
其他文件可以定義相同名字的函數(shù);
-
該函數(shù)不能被其他文件調(diào)用;
static修飾變量的作用與好處
修飾局部變量:存在于靜態(tài)存儲區(qū),補初始化內(nèi)容為0,作用域在當(dāng)前函數(shù)/語句塊;
修飾全局變量:存在于靜態(tài)存儲區(qū),不初始化內(nèi)容為0,作作用域只在當(dāng)前文件;
用static修飾變量的好處是:
-
其他文件可以定義相同名字的變量;
-
該變量不能被其他文件調(diào)用;
關(guān)鍵字volatile有什么含意?并給出三個不用的例子
volatile指的是易變的。 用以告訴編譯器被volatile修飾的變量隨時可能被改變。
以下場合需要用到volatile修飾:
-
中斷服務(wù)程序中修改的供其他程序檢測的變量;
-
多任務(wù)環(huán)境下共享的標(biāo)志;
-
存儲器映射的硬件寄存器;
關(guān)鍵字 _interrupt
_interrupt是用來定義中斷服務(wù)子程序ISR的,它有以下幾個特點:
-
ISR不能返回一個值;
-
ISR不能傳遞參數(shù);
-
最好不要做浮點運算;
-
最好不要加打??;
關(guān)鍵字const有什么含義
const代表著只讀,讓編譯器去保護那些不希望被改變的參數(shù)。
-
定義變量,變量的值不能被改變
-
定義指針,指針的值不能被改變
-
定義類的成員函數(shù),成員函數(shù)不能改變類的變量
以下代碼聲明的含義是什么
-
const int a;
-
int const a;
-
const int *a;
-
int* const a;
-
const int* const a;
-
a是一個常數(shù)整數(shù)
-
a是一個常數(shù)整數(shù)
-
a是一個指向常數(shù)整數(shù)的指針,指針的值不可修改,但是指針可以修改
-
a是一個指向整數(shù)的常量指針,整數(shù)的值可以修改,但是指針不可修改
-
a是一個指向const整數(shù)的const指針,整數(shù)和指針的值都不可以修改
c和c++ 中的struct有什么不同
-
C中的struct不能有成員函數(shù),而C++的struct可以。
-
C中struct的默認權(quán)限是public,而C++的struct是private。
內(nèi)存
內(nèi)存最小存儲單元以及內(nèi)存最小計量單元是什么
內(nèi)存最小存儲單元是Bit(二進制位)
內(nèi)存最小計量單元是Byte(字節(jié))
描述一下內(nèi)存分區(qū)
程序在運行前:代碼區(qū)、BSS段(為未初始化數(shù)據(jù)區(qū))、data段(初始化數(shù)據(jù)區(qū));
程序在運行后:堆區(qū)、棧區(qū)、全局區(qū)(靜態(tài)區(qū))、代碼區(qū)、文字常量區(qū)。
stack棧與heap堆的區(qū)別
stack棧由系統(tǒng)自動分配,其地址和容量是系統(tǒng)定的,是一塊連續(xù)的內(nèi)存(Window下是2M);
heap堆是用戶自己用malloc申請的,char p = (char)malloc(),它是不連續(xù)的。
malloc()與new()的區(qū)別
-
malloc
-
是在堆中申請內(nèi)存,申請需要指定大小
-
返回void*類型,需使用強制轉(zhuǎn)換
-
失敗返回NULL
-
new
-
是在自由存儲區(qū)申請內(nèi)存,無需指定大小
-
返回對象類型指針,無需轉(zhuǎn)換,安全
-
失敗返回mac_alloc異常
內(nèi)存溢出一般是由什么導(dǎo)致的
-
動態(tài)申請的空間沒有回收
-
數(shù)組越界訪問
變量
變量的命名規(guī)則
變量名由字母、數(shù)字、下劃線組成,但是不能以下劃線開頭。
變量的聲明和定義有什么區(qū)別
變量的定義需要定義存儲空間;
變量的聲明不需要建立存儲空間。
描述普通局部變量、普通全局變量、靜態(tài)局部變量、靜態(tài)全局變量的區(qū)別
普通局部變量:存在于棧區(qū),不初始化內(nèi)容隨機,只作用于當(dāng)前語句塊,語句塊結(jié)束變量空間釋放。
普通全局變量:存在于全局區(qū),不初始化內(nèi)容為0,作用于當(dāng)前文件,也能被其他文件用extern調(diào)用,進程結(jié)束變量空間才被釋放;
靜態(tài)局部變量:存在于靜態(tài)存儲區(qū),不初始化內(nèi)容為0,作用于復(fù)合語句,進程結(jié)束變量空間才被釋放;
靜態(tài)全局變量:存在于靜態(tài)存儲區(qū),不初始化內(nèi)容為0,只作用于當(dāng)前文件,進程結(jié)束變量空間才被釋放。
用變量a進行定義
-
一個整型數(shù)
int a
-
一個指向整型數(shù)的指針
int *a
-
一個指向指針的指針,它指向的指針是指向一個整型數(shù)
int **a
-
一個有10個整型數(shù)的數(shù)組
int a[10]
-
一個有10指針的數(shù)組,該指針是指向一個整型數(shù)
int *a[10]
-
一個指向有10個整型數(shù)數(shù)組的指針
int (*a)[10]
-
一個指向函數(shù)的指針,該函數(shù)有一個整型數(shù)參數(shù)并返回一個整型數(shù)
int (*a)(int)
-
一個有10個指針的數(shù)組,該指針指向一個函數(shù),該函數(shù)有一個整型數(shù)參數(shù)并返回一個整型
int (*a[10])(int)
如何定義一個已經(jīng)引用過的全局變量
-
頭文件定義
-
extern調(diào)用
數(shù)組
數(shù)組的特點
-
所有成員都是相同的數(shù)據(jù)類型
-
所有成員再內(nèi)存中地址是連續(xù)的
數(shù)組的分類
數(shù)組的分類有:靜態(tài)數(shù)組、動態(tài)數(shù)組。
靜態(tài)數(shù)組:在程序運行前就確定了大小,且運行中大小不能更改。
動態(tài)數(shù)組:主要是在堆中申請的空間,大小在運行中確定,且可以更改。
一維數(shù)組在不初始化、部分初始化、完全初始化的區(qū)別
不初始化:如果是局部數(shù)組,內(nèi)容隨機;如果是全局數(shù)組,內(nèi)容為0;
部分初始化:未初始化的部分自動補0;
完全初始化:數(shù)組大小由初始化的個數(shù)確定。
數(shù)組作為類型、作為地址、取地址的區(qū)別
數(shù)組作為類型:代表整個數(shù)組的大??;
數(shù)組作為地址:代表數(shù)組首元素地址;
數(shù)組取地址:代表數(shù)組首地址。
二維數(shù)組在物理和邏輯上的區(qū)別
在物理上是一維的,在邏輯上是二維的。
函數(shù)
函數(shù)的定義與函數(shù)的聲明有何區(qū)別
函數(shù)的定義:指的是對函數(shù)功能的確立,包括函數(shù)類型、函數(shù)名、形參、函數(shù)體。
函數(shù)的聲明:告訴編譯器這個函數(shù)的類型、名字、形參。
宏函數(shù)的概念以及作用
把一些短而小、使用頻繁的函數(shù)寫成宏函數(shù);
由于宏函數(shù)沒有普通函數(shù)的壓棧、跳轉(zhuǎn)、返回等開銷,可以提高代碼效率。
指針
描述一下32位或64位平臺下指針的大小
32位平臺:任意類型的指針大小為4字節(jié);
64位平臺:任意類型的指針大小為8字節(jié);
指針數(shù)組的概念
本質(zhì)是一個數(shù)組,數(shù)組中的每一個元素都是一個指針。
使用realloc給已分配的堆區(qū)空間追加空間時需要注意什么
用指針變量保存realloc的返回值。
什么情況下會出現(xiàn)野指針
-
指針未初始化
-
指針釋放后未置空
-
指針操作超出其作用域
引用與指針的區(qū)別
-
引用必須初始化,指針不必初始化
-
引用初始化用不能被改變,指針可改變
-
引用不可指向空值,指針可指向空值
指針作為函數(shù)參數(shù)的輸入特性和輸出特性
輸入特性:主函數(shù)分配空間,被調(diào)函數(shù)使用空間;
輸出特性:被調(diào)函數(shù)分配空間,主函數(shù)使用空間。
(void )ptr 和((void**))ptr 的結(jié)果是否相同?其中ptr為同一個指針
一樣的。
結(jié)構(gòu)體
結(jié)構(gòu)體和共用體的區(qū)別是啥
結(jié)構(gòu)體的成員擁有獨立的空間;
共用體的成員共用一塊空間,并且成員能訪問的口昂見大小由成員自身類型決定。
如何理解結(jié)構(gòu)體的淺拷貝和深拷貝
當(dāng)結(jié)構(gòu)體中出現(xiàn)指針成員的時候容易出現(xiàn)淺拷貝和深拷貝的問題。
淺拷貝:兩個結(jié)構(gòu)體的指針成員指向同一塊區(qū)域空間,結(jié)構(gòu)體釋放時這塊空間會被多次釋放;
深拷貝:兩個結(jié)構(gòu)體指針成員指向不空的區(qū)域空間,只是內(nèi)容拷貝一份,結(jié)構(gòu)體釋放時不會出現(xiàn)同一個空間被釋放多次的情況。
文件
文件緩沖的幾個刷新方式
-
行緩沖
-
滿緩沖
-
強制緩沖
-
關(guān)閉緩沖
談?wù)勎募姆诸?/h4>
文件分為二進制文件和文本文件。
二進制文件基于值編碼,需要根據(jù)具體的應(yīng)用才能知道某個值的意思;
文本文件基于字符編碼,一個字節(jié)一個意思,可以通過記事本打開。
進程
進程通信(IPC)的方式
-
管道(pipe/fifo)
-
消息隊列
-
共享內(nèi)存
-
套接字socket
-
信號
-
信號量
字節(jié)對齊
對齊規(guī)則
規(guī)則一:第一個成員的首地址為0。(默認4字節(jié)對齊)
規(guī)則二:每個成員的首地址是自身大小的整數(shù)倍。(成員自身對齊)
規(guī)則三:結(jié)構(gòu)體變量的總大小是結(jié)構(gòu)體里最大的成員的整數(shù)倍。(結(jié)構(gòu)體本身對齊)
例子1
struct?test
{
char?x1;
short?x2;
float?x3;
char?x4;
};
答案:整個結(jié)構(gòu)所占據(jù)空間為12字節(jié)。
例子2
#pragma?pack(1)?//讓編譯器對這個結(jié)構(gòu)作1字節(jié)對齊
struct?test
{
char?x1;
short?x2;
float?x3;
char?x4;
};
#pragma?pack()?//取消1字節(jié)對齊,恢復(fù)為默認4字節(jié)對齊
這時候sizeof(struct test)的值為8。
因為使用偽指令#pragma pack (n),C編譯器將按照n個字節(jié)對齊。
使用偽指令#pragma pack(),取消自定義字節(jié)對齊方式,一般都是成對存在的。
#pragma?pack?(2)?/*指定按2字節(jié)對齊*/
struct?C
{
????????char?b;
????????int?a;
????????short?c;
};
#pragma?pack?()?/*取消指定對齊,恢復(fù)缺省對齊*/
sizeof(struct C)值是8。
#pragma?pack?(1)?/*指定按1字節(jié)對齊*/
struct?D
{
????????char?b;
????????int?a;
????????short?c;
};
#pragma?pack?()?/*取消指定對齊,恢復(fù)缺省對齊*/
sizeof(struct D)值是7。
代碼
*ptr++ 、++ptr和++ptr相同嗎?
ptr++等價于(ptr++);
++ptr等價于++(ptr);
++ptr等價于(++ptr);
請問以下代碼有什么問題
int main()
{
char a;
char *str=&a;
strcpy(str,"hello");
printf(str);
return 0;
}
沒有給str分配空間,將一個字符串支復(fù)制給一個字符變量指針將會發(fā)生異常,因為越界讀寫導(dǎo)致系統(tǒng)崩潰。 正確修正方法:
char a[10]; char *str = a;
以下代碼有什么出錯的地方
char* s="AAA";
printf("%s",s);
s[0]='B';
printf("%s",s);
編譯正確,運行錯錯誤,“AAA”是字符串常量,s[0]試圖修改字符串常量的指值,字符串常量不能修改。
以下代碼有什么出錯的地方
wap( int* p1,int* p2 )
{
int * p; //(int)malloc(4); is ok
*p = *p1;
*p1 = *p2;
*p2 = *p;
}
沒有給指針p分配空間,為空指針,無法存儲指針p1的值。
編寫memcpy函數(shù)
void* memcpy(void* dest,const void* src,int size)
{
if(dest == NULL || src == NULL)
return dest;
while(size--)
{
*(char*)dest = *(char*)src;
dest = dest+1;
src = src+1;
}
retern dest;
}
編寫strcpy函數(shù)并解釋為什么要返回char型
char* strcpy(char* strDest,const char* strsSrc)
{
if(strDest == NULL || strSrc == NULL)
return NULL;
char*p = strDest;
while(*strsSrc != '\0')
{
*p++ = *strsSrc++;
}
*p = *strSrc;
return strdDest;
}
返回char類型是為了增加靈活性,比如鏈?zhǔn)讲僮鳎纾?/p>
int length = strlen( strcpy(str,"Hello World") );
計算題
unsigned?char?*p1;
unsigned?long?*p2;
p1=(unsigned?char?*)0x801000;
p2=(unsigned?long?*)0x810000;
請問p1+5=?;
p2+5=?;
0x801005、0x810014
32位機unsigned long為4個字節(jié),64位機占8個字節(jié)。
計算題
main()
{
int?a[5]={1,2,3,4,5};
int?*?ptr=(int*)(&a+1);
printf(“%d,%d”,*(a+1),*(ptr-1));
}
標(biāo)準(zhǔn)答案:2,5
關(guān)鍵點在&a。
a既是數(shù)據(jù)名,又是指向數(shù)組第一個元素的指針。sizeof(a)=20, 此時a的類型為int[5]數(shù)組。sizeof(a)=4,因為有取值符,表示把a當(dāng)成一個指針(int*),而a指向數(shù)組的首地址。
(&a+1)先取變量a的地址,并根據(jù)a的地址獲得下一個與a同類型的相鄰地址。根據(jù)前面所說的a的類型為int[5]數(shù)組。&a+1=&a+sizeof(5*int),因此&a+1指向的地址為 &a[5] (數(shù)組a[5]的下一個地址)。
如果將&a+1改為a+1,則答案為:1
這段代碼執(zhí)行有什么問題?
#define?Max_CB?500
void?LmiQueryCSmd(StructMSgCB?*?pmsg)
{
unsigned?char?ucCmdNum;
......??
for(ucCmdNum=0;ucCmdNum<Max_CB;ucCmdN
um++)
{
......;
}???
會死循環(huán)。
unsigned char的取值范圍為:0-255,而Max_CB最大為500,ucCmdNum無法達到。
一句代碼實現(xiàn)x是否為2的若干次冪的判斷
return?x&(x-1)?0:1
下面的代碼輸出是什么,為什么?
void?foo(void)
{
????????unsigned?int?a?=?6;
????????int?b?=?-20;
????????(a+b>?6)??puts(">?6")?:?puts("<=?6");
}
標(biāo)準(zhǔn)答案:輸出>6
當(dāng)表達式中存在有符號類型和無符號類型時,所有的數(shù)都自動轉(zhuǎn)換為無符號類型。因此-20 變成了一個非常大的正整數(shù),所以該表達式計算出的結(jié)果大于6 。
下面的代碼片段的輸出是什么,為什么?
char?*ptr;
if?((ptr?=?(char?*)malloc(0))?==?NULL)
puts("Gota?null?pointer");
else
puts("Gota?valid?pointer");
標(biāo)準(zhǔn)答案:Got a valid pointer
malloc(0)是指分配內(nèi)存大小為零;NULL是不指向任何實體
malloc(0)也是一種存在不是NULL,但是如果對其進行讀寫操作則會報錯。
怎么判斷鏈表中是否有環(huán)?
標(biāo)準(zhǔn)答案:快慢指針法。
用兩個指針來遍歷這個單向鏈表,第一個指針p1,每次走一步;第二個指針p2,每次走兩步;當(dāng)p2 指針追上p1的時候,就表明鏈表當(dāng)中有環(huán)路了。
Bool?hasCycle(ListNode*?Head)
{
??if(Head?==?NULL)
???return?flase;
???
???ListNode*?fast?=?Head;
???ListNode*?slow?=?Head;
???
???while(fast?!=?NULL?&&?fast->nest?!=?NULL)
???{
?????slow?=?slow->next;
?????fast?=?fast->next->next;
?????if(slow?==?fast)
???????return?ture;
???}
????return?flase;
}
排序 從小到大
冒泡法
就是在每一輪的篩選中找出相鄰元素組中較大的那個數(shù)。
在不斷的交換中將當(dāng)前元素組中最大的數(shù)賦值給當(dāng)前元素組中最后一個元素空間
#?include<stdio.h>
int?main()
{
?int?a[10]?=?{6,7,8,9,10,1,2,3,4,5};
?int?temp;
?for(int?i=0;i<10;i++)
?{
????for(int?j=0;j<10-i;j++)
????{
??????if(a[j]?>?a[j+1])
??????{
????????temp?=?a[j];
????????a[j]?=?a[j+1];
????????a[j+1]?=?temp;
??????}
????}
?}
?for(i=0;i<10;i++)
?{
???printf("out?is?%d\n",a[i]);
?}
?return?0;
}
小結(jié)
我記得曾經(jīng)有人說過,思想和行動的區(qū)別在于:
想談戀愛卻高呼自由可貴,想進大廠卻不想工作,想當(dāng)大牛卻不想學(xué)習(xí),每個人都知道明天必須披荊斬棘的活下去,卻依舊渾渾噩噩的度過今天。
不用去懷疑自己的能力,你只需要一份靠譜的學(xué)習(xí)資料,一個學(xué)習(xí)的deadline以及一個沒學(xué)完就打爆你狗頭的人,很快你就會被自己的才華和能力所驚艷。
我收集了一些linux的資料,算法小抄和計算機基礎(chǔ)的資料。
以下資料僅供個人學(xué)習(xí)使用,歡迎大家一起學(xué)習(xí)探討。
linux保姆級教程完整版文檔資料文章來源:http://www.zghlxwxcb.cn/news/detail-571627.html
希望以上內(nèi)容能幫助到你,祝各位生活愉快。文章來源地址http://www.zghlxwxcb.cn/news/detail-571627.html
到了這里,關(guān)于2023最新C語言經(jīng)典面試題匯總的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!