程序員面試寶典總結1

1.C++ CODE(P29)
int i = 1;
void main(int argc, char ** argv){
int i = i;
}
/*main中的i未定義*/


2.計算X中1個個數(P31)
int onenumber(int x){
int count = 0;
while(x){
count++;
x = x&(x-1);
}
return count;
}


onenumber(9999)-----8
9999-----10011100001111


判斷一個數是否爲2^N
2, 4, 8-- 10, 100, 1000這樣的數X按位與X-1對於0
//返回1---爲2^N
//返回0--否
int fun(int x){
return !(x&(x-1))
}
 
3.printf計算參數時是從右到左壓棧的。。
void main(int argc, char ** argv){
int b =3;
int arr[] = {6, 7, 8, 9, 10};
int *ptr = arr;
*(ptr++)+=123;
printf("%d, %d\n", *ptr, *(++ptr));
}
輸出 8,8


4. 編程風格
if('A' == a){
a++;
}


if(a == 'A'){
a++;
}


第一種,當==寫錯成=時,因不能給常數複製程序會報錯,可以檢測錯誤。


S=Y+J*7;
for(int i=0; i<8; i++){
X = i+Y+J*7;
printf("%d", X);
}


S=Y+J*7;
for(int i=0; i<8; i++){
printf("%d", i+S);
}
第二種,把加法移除循環外,加速程序運行。


5.類型轉換(P34)
void main(int argc, char ** argv){
float a = 1.0f;
cout << (int)a << endl;//浮點轉成整形
cout << &a << endl;//變量地址
cout << (int &)a<< endl;//將指向a的指針變換成int型指針。因將float地址開始出 //sizeof(int)當成int開看待。(浮點數與整//形在內存中不同的存儲方式)
cout <<boolalpha << ( (int)a == (int &)a )<< endl;

a = 0.0f;
cout << (int)a << endl;//浮點轉成整形
cout << &a << endl;//變量地址
cout << (int &)a<< endl;//將指向a的指針變換成int型指針。因將float地址開始出 //sizeof(int)當成int開看待。(浮點數與整形在內存//中不同的存儲方式)
cout <<boolalpha << ( (int)a == (int &)a )<< endl;
}


輸出:false---true


(P34)
void main(int argc, char ** argv){
unsigned int a = 0xfffffff7;
unsigned char i = (unsigned char)a;//uint->uchar發生字節階段(截斷高位)
char *b = (char *)&a;  //指針類型轉變
printf("%08x, %08x", i, *b);
}

輸出:000000f7,fffffff7


6.運算符優先級(P39)
void main(int argc, char ** argv){
unsigned char a = 0xA5;
unsigned char b = ~a>>4+1;  //(~a)>>(4+1); 優先級從低到高>>,+,~
printf("%d", b);
}
輸出:250
a=0xA5 ------16位寄存器 0x00 A5
取反                    0xFF 5A
右移5位 0x07 fA = 250
7. 平均值(P40)
int f(int x, int y){
return (x&y)+((x^y)>>1)//x&y相同一半, 想(x^y)>>1 不同的一半

}


9.最大值(P41)---不用if switch

int max(int x, int y){
return (x+y+abs(x-y))/2;
}


abs函數--#include "math.h"


10.交換x,y--不用中間變量
*************
x = x - y;
y = x + y;
x = y - x;
x+y可能越界
**************
a^a = 0
a^0 = a


      x=x^y;
      y=x^y;
      x=x^y;


10. c++調用被C編譯器編譯後的函數,加extern “C”(P40)
C++支持函數重載,C不支持函數重載。同一函數在C++和C中編譯後的名字不同。(foo函數 C++編譯後函數名_foo_int_int C編譯後的函數名_foo).C++使用extern “C”連接C,解決名字匹配問題。


11 宏(P46)
結構體某個變量相對結構體的偏移量
#define FIND(struc, e) (size_t)&(((struc *)0)->e)


一年中的秒數(忽略閏年)
#define SENCONDS_PER_YEAR (60*60*24*365)UL


最小值
#define MIN(x, y) ( (x) >= (y) ? (y) : (x) )


12 const用途(P47) *********
1 定義常量
2, 修飾函數的參數。參數只能讀,不能修改。(可防止意外改動,提高程序的健壯性)


13 const和#define區別******
都可以定義常量。const常量有類型,define無類型。編譯器可以對const常量類型進行檢查,而define只是簡單的字符替換,可能會出現意想不到的結果。

C編譯器不把const看成編譯期間的常量
const size = 100;
char buf[size];  //編譯錯誤。。。


C++中帶有const函數的只能修改帶有mutable成員變量。
class C{
public:
int incr() const{
m++; //right
d++; //wrong
}
private:
mutable int m;
int d;
}


14 sizeof strlen
1. char * str = "123";
sizeof(str) = 4;//編譯器在後面加了\0
strlen(str) = 3;
2. char str[] = "123";
sizeof(str) = 4;//編譯器在後面加了\0
strlen(str) = 3;
2. char str[100] = "123";
sizeof(str) = 100; 
strlen(str) = 3;


當str[10]=“0123456789”,編譯器報錯arry bounds overflow。


15.
結構體長度
一、結構體變量中成員的偏移量必須是成員大小的整數倍(0被認爲是任何數的整數倍)
二、結構體大小必須是所有成員大小的整數倍。
struct{
short a; //偏移量0
short b; //偏移量2
short c; //偏移量4
}
總長度4+2 = 6;滿足第二條件
struct{
long  a; //偏移量0
short b; //偏移量4
}
總長度4+2 = 6;不滿足第二條件,長度有6變爲8;
*****************
計算對象的大小,只看其中的成員變量。內存對齊情況,參考結構體大小計算。
sizeof只計算棧中分配的大小。static變量不計算在內。
class A1{
public:
int a;
static int b;
A1();
~A!();
}
sizeof(A1)=4;
class A2{
public: 
int a;
char b;
}
sizeof(A2) =8;


sizeof運算符  strlen函數


int *b[10];   sizeof(b)=10*4=40
int **a[3][4]; sizeof(a)=3*4*4=48


16.內聯函數和宏定義(P60)
區別:
1.內聯函數嵌入到目標文件中,不用中斷調用,加快程序運行速度。宏定義編譯時的代碼替換
2.內聯函數檢測參數類型,宏定義則沒有。內聯更安全,但是是以犧牲存儲空間爲代價。
內聯函數用處:
1.代碼被重複調用
2.函數只有簡單的幾行


17 指針 引用區別(P62)
1.非空區別。指針可以爲空。引用初始化必須賦初值
2.修改區別。指針可以修改。引用不可以更改
3.合法性區別。指針測試是否爲空(strlen)。引用必須測試其合法性

18 指針合法性(P66)
char *strA(){
char str[] = "abcd"; //堆棧空間。函數推出,堆棧空間無效。
return str;
}
修改爲
char *strA(){
static char str[] = "abcd"; //靜態存儲空間
return str;
}
char *str="avdd";    //全局空間,只讀。str[0]='1'出錯。
char str[] = "abcd"; //局部空間。str[0] = '1'有效。


19 指針的減法(指針類型的差值)(P68)
int a[3]={0, 1, 2};
int *p, *q;
p = a;
q = &a[2];
cout<<a[q-p]<<endl;
輸出爲:a[p-q]=a[8/sizof(int)]=a[2]=2;


20.代碼輸出 1
class A{
public:
A() {m_a =1; m_b=2;}
~A(){};
void fun(){printf("%d%d", m_a, m_b);}
private:
int m_a;
int m_b;
};


class B{
public:
B() {m_a =3;}
~A(){};
void fun(){printf("%d", m_a);}
private:
int m_a;
};


void main(){
A a;
P* pb = (B*)(&a);
pb->fun();
}


21. 
A.函數的形參在函數未調用之前分配存儲空間    // 調用時分配內存
B.若函數的定義出現在主函數之前,則可以不必再說明 //函數需在調用之前什麼,與主函數沒有什麼關係
C.若一個函數沒有返回值,則什麼值都不返回 //main 默認返回0
D.一般來說,函數的形參和實參的類型一致




22 s.p[i]====*(s.p+i)
 struct S{
int i;
int *p;
}
main(){
S s;
int *p = &s.i;
p[0] = 4;
p[1] = 3;
s.p =p;
s.p[1] = 1;
s.p[0] = 2; //程序崩潰。 *((int *)1) = 2;




23函數指針
函數指針 void (*f)();
返回指針函數 void *f();
const指針 const char *;
指向const變量的指針 char * const;
指向const變量的const指針 const char *const;



24 一位數組取指針,變爲指向二維數組的指針


int a[] = {1, 2, 3, 4, 5};
int *ptr = (int *)(&a +1) //等價於a+6
printf(" %d %d" , *(a+1), *(ptr -1));
輸出爲2,5


25. 迷途指針 空指針
迷途指針  -- delete一個指針,釋放內存,但是指針還存在。不安全,通過賦值爲0變爲空指針。
指針指向內存位置0;


26 malloc/free new/delete區別
1.malloc/free函數    new/delete運算符
2. new/delete爲對象分配內存。對象初始化時調用構造函數,消亡前調用析構函數,malloc/free做不到。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章