C/C++指針ios
int a; int* p = &a; // 指向a地址的指針*pc++
一、與const一塊兒的時候 char * const p; // 指針不可變,也就是指針只能指向一個地址char* p的指針; char const * p; // 所指內容不可改,也就是p是常量字符串 char const * const p; // 內容和指針都不能改 const char * const p; // 同上...內容和指針不能改 二、str[]和str的區別程序員
#include <iostream> using namespace std; int main() { char str1[] = "abc"; char str2[] = "abc"; const char str3[] = "abc"; const char str4[] = "abc"; const char *str5 = "abc"; const char *str6 = "abc"; char *str7 = "abc"; char *str8 = "abc"; cout << ( str1 == str2 ) << endl; cout << ( str3 == str4 ) << endl; cout << ( str5 == str6 ) << endl; cout << ( str7 == str8 ) << endl; }
結果是0011, 這但是說是一個深拷貝/淺拷貝的問題.當字符串是數組形式聲明並初始化,編譯器認爲是新數組,分配新空間,但不是深拷貝,由於根本就不算拷貝.而若是是相同的字符串,用指針聲明,那就是比較若是有同樣的字符串,就直接把新指針指過去,這是正宗的淺拷貝.面試
三、str[]用sizeof判斷會出錯麼?算法
#include <iostream> using namespace std; int MyStrlen( char str[] ) { return ( int )( sizeof( str ) - 1 ); } int main() { char str[] = "mimiasd"; cout << MyStrlen( str ) << endl; }
不管什麼時候,返回的老是3。當用函數傳遞的數組指針的時候就自動退化爲指針了,而指針的長度是4,減去1天然就是3.可是若是按照下面代碼就能夠獲得正常的值:數據庫
char str[] = "mimiasd"; int len = sizeof( str ) - 1; // 減1是爲了去掉'/0'。 cout << len << endl; // 結果爲7。
四、注意數組指針和指針數組
#include <iostream> using namespace std; int main() { int a[ 5 ] = { 1, 2, 3, 4, 5 }; int *ptr = ( int* )( &a + 1 ); cout << *( a + 1 ) << " " << *( ptr - 1 ) << endl; }
答案是2 5,首先,a是一個數組,因此編譯器解釋&a就是a的所有長度,就是說(&a+1)也就是說移動了一個數組,指向了並不存在的a[5],因此ptr-1纔會指向a數組的最後一個元素a[4],而a+1和a[1]是同樣的...因此答案是25,若是你去掉了(&a+1)的括號,那麼答案就是想固然的21了。網絡
五、注意指針要分配給足夠的空間多線程
#include <iostream> #include <string.h> using namespace std; int main() { char a; char *str = &a; strcpy( str, "hello" ); cout << str << endl; }
運行輸出後程序由於訪問了沒有分配的空間,固然崩潰了.若是你只strcpy(str,"");那程序是能夠正常運行的.併發
六、當心編譯器的指針字符串初始化
#include <iostream> using namespace std; int main() { char *s = "AAA"; cout << s << endl; s[ 0 ] = 'B'; cout << s << endl; }
這段程編譯器報告正常, 輸出AAA後報錯,由於當在第一句初始化的時候,編譯器就認爲這是個字符串常量了...再作數組操做的時候確定錯了羅...最好的習慣是聲明一個指針,用new分配空間,而後用庫函數操做,好比strcpy,strcat等等...
七、讓人一眼看上去迷糊的函數指針
int ( *s[ 10 ] )( int );
其實這是一個函數指針數組,指向了一組int fun(int)的函數,第一眼確實讓人有點迷糊...可是請習慣這樣...
八、注意函數傳遞指針的時候的副本
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> using namespace std; void GetMemory( char *p ) { p = new char[ 100 ]; strcpy( p, "hello world" ); } int main() { char *str = NULL; GetMemory( str ); cout << str; delete [] str; str = NULL; }
緣由很簡單...GetMemory這個函數出問題了!函數參數是不能傳遞分配空間的...由於傳遞過去其實是一個副本p...不能返回的...並且你在delete那就是件很危險的。
能夠以下修改代碼:
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> using namespace std; void GetMemory( char **p ) { *p = new char[ 100 ]; strcpy( *p, "hello world" ); } int main() { char *str = NULL; GetMemory( &str ); cout << str; delete [] str; str = NULL; }
9、請時刻記住要初始化字符串
#include <iostream> #include <string.h> using namespace std; int main() { char a[ 10 ]; cout << strlen( a ) << " " << sizeof( a ) << endl; }
輸出是2 10。其實strlen函數的結果和是否初始化有關的...雖然你分配了空間..可是沒有初始化..庫函數會出錯的..sizeof不受影響...切忌初始化哦....
十、小括號、大區別 char (*str)[20]; // str是一個數組指針,即指向數組的指針. char *str[20]; // str是一個指針數組,其元素爲指針型數據.
#include <iostream> #include <string.h> #include <malloc.h> #include <stdio.h> #include <stdlib.h> #include <memory.h> using namespace std; typedef struct AA { int b1:5; int b2:2; } AA; int main() { AA aa; char cc[ 100 ]; strcpy( cc, "0123456789abcdefghijklmnopqrstuvwxyz" ); memcpy( &aa, cc, sizeof( AA ) ); cout << aa.b1 << endl; cout << aa.b2 << endl; }
首 先sizeof(AA)的大小爲4,b1和b2分別佔5bit和2bit.通過strcpy和memcpy後,aa的4個字節所存放的值是: 0,1,2,3的ASC碼,即00110000,00110001,00110010,00110011因此,最後一步:顯示的是這4個字節的前5位,和 以後的2位分別爲:10000,和01,由於int是有正負之分。
預處理器(Preprocessor)
一、用預處理指令#define 聲明一個常數,用以代表1年中有多少秒(忽略閏年問題)
#include <iostream> #include <string.h> #define SECONDS_PER_YEARS 60 * 60 * 24 * 365UL using namespace std; int main() { unsigned long mimiasd = SECONDS_PER_YEARS; cout << mimiasd << endl; }
2、寫一個"標準"宏MIN ,這個宏輸入兩個參數並返回較小的一個。
#include <iostream> using namespace std; #define MIN( a, b ) ( a < b ? a : b ) int main() { int a, b; cin >> a; cin >> b; cout << "The min number is : " << MIN( a, b ) << endl; }
least = MIN(*p++, b);
輸出結果爲一地址表示的負數。 p++中++的優先級大於, 因此至關與*(p++).
三、預處理器標識#error的目的是什麼?
#ifdef XXX ... #error "XXX has been defined" #else #endif 這樣,若是編譯時出現錯誤,輸出了XXX has been defined,代表宏XXX已經被定義了。
死循環(Infinite loops)
四、 嵌入式系統中常常要用到無限循環,你怎麼樣用C編寫死循環呢? 首選的方案是:
while(1) { }
一些程序員更喜歡以下方案:
for(;;) { }
這個實現方式讓人爲難,由於這個語法沒有確切表達到底怎麼回事。若是一個應試者給出這個做爲方案,我將用這個做爲一個機會去探究他們這樣作的基本原理。
第三個方案是用 goto
Loop: ... goto Loop;
應試者如給出上面的方案,這說明或者他是一個彙編語言程序員(這也許是好事)或者他是一個想進入新領域的BASIC/FORTRAN程序員。
數據聲明(Data declarations)
a) int a; // An integer b) int *a; // A pointer to an integer c) int **a; // A pointer to a pointer to an integer d) int a[10]; // An array of 10 integers e) int *a[10]; // An array of 10 pointers to integers f) int (*a)[10]; // A pointer to an array of 10 integers g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
Static
六、 關鍵字static的做用是什麼? 這個簡單的問題不多有人能回答徹底。在C語言中,關鍵字static有三個明顯的做用:
Const
7、下面的聲明都是什麼意思? const int a; int const a; const int a; int * const a; int const * a const; /*****/ 前兩個的做用是同樣,a是一個常整型數。第三個意味着a是一個指向常整型數的指針(也就是,整型數是不可修改的,但指針能夠)。第四個意思a是一個指向整型數的常指針(也就是說,指針指向的整型數是能夠修改的,但指針是不可修改的)。最後一個意味着a是一個指向常整型數的常指針(也就是說,指針指向的整型數是不可修改的,同時指針也是不可修改的)。若是應試者能正確回答這些問題,那麼他就給我留下了一個好印象。順帶提一句,也許你可能會問,即便不用關鍵字 const,也仍是能很容易寫出功能正確的程序,那麼我爲何還要如此看重關鍵字const呢?我也以下的幾下理由:
八、關鍵字volatile有什麼含意?並給出三個不一樣的例子。 一個定義爲volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都當心地從新讀取這個變量的值,而不是使用保存在寄存器裏的備份。下面是volatile變量的幾個例子:
位操做(Bit manipulation)
9、嵌入式系統老是要用戶對變量或寄存器進行位操做。給定一個整型變量a,寫兩段代碼,第一個設置a的bit 3,第二個清除a 的bit 3。在以上兩個操做中,要保持其它位不變。
#define BIT3 (0x1 訪問固定的內存位置(Accessing fixed memory locations)
十、嵌入式系統常常具備要求程序員去訪問某特定的內存位置的特色。在某工程中,要求設置一絕對地址爲0x67a9的整型變量的值爲0xaa66。編譯器是一個純粹的ANSI編譯器。寫代碼去完成這一任務。 這一問題測試你是否知道爲了訪問一絕對地址把一個整型數強制轉換(typecast)爲一指針是合法的。這一問題的實現方式隨着我的風格不一樣而不一樣。典型的相似代碼以下:
int *ptr; ptr = (int *)0x67a9; *ptr = 0xaa55;
A more obscure approach is: 一個較晦澀的方法是:
*(int * const)(0x67a9) = 0xaa55;
即便你的品味更接近第二種方案,但建議你在面試時使用第一種方案。
中斷(Interrupts)
__interrupt double compute_area (double radius) { double area = PI * radius * radius; printf("\nArea = %f", area); return area; }
這個函數有太多的錯誤了,以致讓人不知從何提及了: 1)ISR 不能返回一個值。若是你不懂這個,那麼你不會被僱用的。 2) ISR 不能傳遞參數。若是你沒有看到這一點,你被僱用的機會等同第一項。 3) 在許多的處理器/編譯器中,浮點通常都是不可重入的。有些處理器/編譯器須要讓額處的寄存器入棧,有些處理器/編譯器就是不容許在ISR中作浮點運算。此外,ISR應該是短而有效率的,在ISR中作浮點運算是不明智的。 4) 與第三點一脈相承,printf()常常有重入和性能上的問題。若是你丟掉了第三和第四點,我不會太爲難你的。不用說,若是你能獲得後兩點,那麼你的被僱用前景愈來愈光明瞭。
十二、下面的代碼輸出是什麼,爲何?
#include <iostream> #include <stdio.h> using namespace std; void foo(void) { unsigned int a = 6; int b = -20; ( a + b > 6 ) ? puts( "> 6" ) : puts( "6" ); } int main() { foo(); }
輸出>6。緣由是當表達式中存在有符號類型和無符號類型時全部的操做數都自動轉換爲無符號類型。所以-20變成了一個很是大的正整數,因此該表達式計算出的結果大於6。
unsigned int zero = 0; unsigned int compzero = 0xFFFF; /*1's complement of zero */
對於一個int型不是16位的處理器爲說,上面的代碼是不正確的。應編寫以下:
unsigned int compzero = ~0;
動態內存分配(Dynamic memory allocation)
char *ptr; if ((ptr = (char *)malloc(0)) == NULL) puts("Got a null pointer"); else puts("Got a valid pointer");
這是一個有趣的問題。最近在個人一個同事不經意把0值傳給了函數malloc,獲得了一個合法的指針以後,我纔想到這個問題。這就是上面的代碼,該代碼的輸出是"Got a valid pointer"。我用這個來開始討論這樣的一問題,看看被面試者是否想到庫例程這樣作是正確。獲得正確的答案當然重要,但解決問題的方法和你作決定的基本原理更重要些。
Typedef
15 Typedef 在C語言中頻繁用以聲明一個已經存在的數據類型的同義字。也能夠用預處理器作相似的事。例如,思考一下下面的例子:
#define dPS struct s * typedef struct s * tPS;
以上兩種狀況的意圖都是要定義dPS 和 tPS 做爲一個指向結構s指針。哪一種方法更好呢?(若是有的話)爲何? 這是一個很是微妙的問題,任何人答對這個問題(正當的緣由)是應當被恭喜的。答案是:typedef更好。思考下面的例子: dPS p1,p2; tPS p3,p4; 第一個擴展爲 struct s * p1, p2 上面的代碼定義p1爲一個指向結構的指,p2爲一個實際的結構,這也許不是你想要的。第二個例子正確地定義了p3 和p4 兩個指針。
16 . C語言贊成一些使人震驚的結構,下面的結構是合法的嗎,若是是它作些什麼?
int a = 5, b = 7, c; c = a+++b;
這個問題將作爲這個測驗的一個愉快的結尾。無論你相不相信,上面的例子是徹底合乎語法的。問題是編譯器如何處理它?水平不高的編譯做者實際上會爭論這個問題,根據最處理原則,編譯器應當能處理儘量全部合法的用法。所以,上面的代碼被處理成:
c = a++ + b;
所以, 這段代碼持行後a = 6, b = 7, c = 12。 若是你知道答案,或猜出正確答案,作得好。若是你不知道答案,我也不把這個看成問題。我發現這個問題的最大好處是這是一個關於代碼編寫風格,代碼的可讀性,代碼的可修改性的好的話題。
一、局部變量可否和全局變量重名?
答:能,局部會屏蔽全局。要用全局變量,須要使用"::"
局部變量能夠與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。對於有些編譯器而言,在同一個函數內能夠定義多個同名的局部變量,好比在兩個循環體內都定義一個同名的局部變量,而那個局部變量的做用域就在那個循環體內。
二、如何引用一個已經定義過的全局變量?
答:extern
能夠用引用頭文件的方式,也能夠用extern關鍵字,若是用引用頭文件方式來引用某個在頭文件中聲明的全局變理,假定你將那個變寫錯了,那麼在編譯期間會報錯,若是你用extern方式引用時,假定你犯了一樣的錯誤,那麼在編譯期間不會報錯,而在鏈接期間報錯。
三、全局變量可不能夠定義在可被多個.C文件包含的頭文件中?爲何?
答:能夠,在不一樣的C文件中以static形式來聲明同名全局變量。
能夠在不一樣的C文件中聲明同名的全局變量,前提是其中只能有一個C文件中對此變量賦初值,此時鏈接不會出錯.
四、語句for( ;1 ;)有什麼問題?它是什麼意思?
答:和while(1)相同。
五、do……while和while……do有什麼區別?
答:前一個循環一遍再判斷,後一個判斷之後再循環
六、請寫出下列代碼的輸出內容
如下是引用片斷:
#include <stdio.h> int main() { int a,b,c,d; a=10; b=a++; c=++a; d=10*a++; printf("b,c,d:%d,%d,%d",b,c,d); return 0; }
答:10,12,120
七、static全局變量與普通的全局變量有什麼區別?static局部變量和普通局部變量有什麼區別?static函數與普通函數有什麼區別?
全局變量(外部變量)的說明以前再冠以static 就構成了靜態的全局變量。全局變量自己就是靜態存儲方式, 靜態全局變量固然也是靜態存儲方式。 這二者在存儲方式上並沒有不一樣。這二者的區別雖在於非靜態全局變量的做用域是整個源程序, 當一個源程序由多個源文件組成時,非靜態的全局變量在各個源文件中都是有效的。 而靜態全局變量則限制了其做用域, 即只在定義該變量的源文件內有效, 在同一源程序的其它源文件中不能使用它。因爲靜態全局變量的做用域侷限於一個源文件內,只能爲該源文件內的函數公用, 所以能夠避免在其它源文件中引發錯誤。
從以上分析能夠看出, 把局部變量改變爲靜態變量後是改變了它的存儲方式即改變了它的生存期。把全局變量改變爲靜態變量後是改變了它的做用域, 限制了它的使用範圍。
static函數與普通函數做用域不一樣。僅在本文件。只在當前源文件中使用的函數應該說明爲內部函數(static),內部函數應該在當前源文件中說明和定義。對於可在當前源文件之外使用的函數,應該在一個頭文件中說明,要使用這些函數的源文件要包含這個頭文件
static全局變量與普通的全局變量有什麼區別:static全局變量只初使化一次,防止在其餘文件單元中被引用;
static局部變量和普通局部變量有什麼區別:static局部變量只被初始化一次,下一次依據上一次結果值;
static函數與普通函數有什麼區別:static函數在內存中只有一份,普通函數在每一個被調用中維持一份拷貝
八、程序的局部變量存在於(堆棧)中,全局變量存在於(靜態區 )中,動態申請數據存在於( 堆)中。
九、設有如下說明和定義:
typedef union {long i; int k[5]; char c;} DATE;
struct data { int cat; DATE cow; double dog;} too;
DATE max;
則語句 printf("%d",sizeof(struct date)+sizeof(max));的執行結果是:52_
答:DATE是一個union, 變量公用空間. 裏面最大的變量類型是int[5], 佔用20個字節. 因此它的大小是20
data是一個struct, 每一個變量分開佔用空間. 依次爲int4 + DATE20 + double8 = 32.
因此結果是 20 + 32 = 52.
固然...在某些16位編輯器下, int多是2字節,那麼結果是 int2 + DATE10 + double8 = 20
十、隊列和棧有什麼區別?
隊列先進先出,棧後進先出
十二、引用與指針有什麼區別? 1) 引用必須被初始化,指針沒必要。 2) 引用初始化之後不能被改變,指針能夠改變所指的對象。 3) 不存在指向空值的引用,可是存在指向空值的指針。
1三、描述實時系統的基本特性 在特定時間內完成特定的任務,實時性與可靠性
1四、 全局變量和局部變量在內存中是否有區別?若是有,是什麼區別? 全局變量儲存在靜態數據庫,局部變量在堆棧
1五、 什麼是平衡二叉樹? 左右子樹都是平衡二叉樹 且左右子樹的深度差值的絕對值不大於1
1六、堆棧溢出通常是由什麼緣由致使的? 沒有回收垃圾資源
1七、 什麼函數不能聲明爲虛函數? constructor
1八、冒泡排序算法的時間複雜度是什麼? O(n^2)
1九、寫出float x 與「零值」比較的if語句。 if(x>0.000001&&x<-0.000001)
Internet採用哪一種網絡協議?該協議的主要層次結構? tcp/ip 應用層/傳輸層/網絡層/數據鏈路層/物理層
Internet物理地址和IP地址轉換採用什麼協議? ARP (Address Resolution Protocol)(地址解析協議)
22.IP地址的編碼分爲哪倆部分? IP地址由兩部分組成,網絡號和主機號。不過是要和「子網掩碼」按位與上以後才能區分哪些是網絡位哪些是主機位。
23.用戶輸入M,N值,從1至N開始順序循環數數,每數到M輸出該數值,直至所有輸出。寫出C程序。 循環鏈表,用取餘操做作
24.不能作switch()的參數類型是: switch的參數不能爲實型。
2五、寫出下列代碼的輸出內容
#include<stdio.h> int inc( int a ) { return( ++a ); } int multi( int *a, int *b, int *c ) { return( *c = *a**b ); } typedef int( FUNC1 )( int in ); typedef int( FUNC2 ) ( int*, int*, int* ); void show( FUNC2 fun, int arg1, int*arg2 ) { FUNC1* p = &inc; int temp = p( arg1 ); fun( &temp, &arg1, arg2 ); printf( "%d\n", *arg2 ); } int main() { int a; show( multi, 10, &a ); return 0; }
結果是110.
2六、請找出下面代碼中的因此錯誤
說明:如下代碼是把一個字符串倒序,如「abcd」倒序後變爲「dcba
一、#include"string.h" 二、main() 三、{ 四、 char*src="hello,world"; 五、 char* dest=NULL; 六、 int len=strlen(src); 七、 dest=(char*)malloc(len); 八、 char* d=dest; 九、 char* s=src[len]; 十、 while(len--!=0) 十一、 d++=s--; 十二、 printf("%s",dest); 1三、 return 0; 1四、}
答: 方法1: int main(){ char* src = "hello,world"; int len = strlen(src); char* dest = (char*)malloc(len+1);//要爲\0分配一個空間 char* d = dest; char* s = &src[len-1];//指向最後一個字符 while( len-- != 0 ) *d++=*s--; *d = 0;//尾部要加\0 printf("%s\n",dest); free(dest);// 使用完,應當釋放空間,以避免形成內存匯泄露 return 0; } 方法2: #include <stdio.h> #include <string.h> main() { char str[]="hello,world"; int len=strlen(str); char t; for(int i=0; i<len/2; i++) { t=str[i]; str[i]=str[len-i-1]; str[len-i-1]=t; } printf("%s",str); return 0; }
1 、-1,2,7,28,,126請問28和126中間那個數是什麼?爲何? 第一題的答案應該是4^3-1=63 規律是n^3-1(當n爲偶數0,2,4) n^3+1(當n爲奇數1,3,5) 答案:63
二、用兩個棧實現一個隊列的功能?要求給出算法和思路! 設2個棧爲A,B, 一開始均爲空.
入隊: 將新元素push入棧A;
出隊: (1)判斷棧B是否爲空; (2)若是不爲空,則將棧A中全部元素依次pop出並push到棧B; (3)將棧B的棧頂元素pop出;
這樣實現的隊列入隊和出隊的平攤複雜度都仍是O(1), 比上面的幾種方法要好。
三、在c語言庫函數中將一個字符轉換成整型的函數是atol()嗎,這個函數的原型是什麼? 函數名: atol 功 能: 把字符串轉換成長整型數 用 法: long atol(const char *nptr); 程序例: #include <stdlib.h> #include <stdio.h> int main(void) { long l; char *str = "98765432";
l = atol(lstr); printf("string = %s integer = %ld\n", str, l); return(0); }
2.對於一個頻繁使用的短小函數,在C語言中應用什麼實現,在C++中應用什麼實現? c用宏定義,c++用inline
3.直接連接兩個信令點的一組鏈路稱做什麼? PPP點到點鏈接
四、軟件測試都有那些種類? 黑盒:針對系統功能的測試 白盒:測試函數功能,各函數接口
五、肯定模塊的功能和模塊的接口是在軟件設計的那個隊段完成的? 概要設計階段
1.進程和線程的差異。 線程是指進程內的一個執行單元,也是進程內的可調度實體. 與進程的區別: (1)調度:線程做爲調度和分配的基本單位,進程做爲擁有資源的基本單位 (2)併發性:不只進程之間能夠併發執行,同一個進程的多個線程之間也可併發執行 (3)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統資源,但能夠訪問隸屬於進程的資源. (4)系統開銷:在建立或撤消進程時,因爲系統都要爲之分配和回收資源,致使系統的開銷明顯大於建立或撤消線程時的開銷。
2.測試方法 人工測試:我的複查、抽查和會審 機器測試:黑盒測試和白盒測試
3.列舉幾種進程的同步機制,並比較其優缺點。 原子操做 信號量機制 自旋鎖 管程,會合,分佈式系統
4.進程之間通訊的途徑 共享存儲系統 消息傳遞系統 管道:以文件系統爲基礎
5.進程死鎖的緣由 資源競爭及進程推動順序非法
12.死鎖的4個必要條件 互斥、請求保持、不可剝奪、環路
14.類的靜態成員和非靜態成員有何區別? 類的靜態成員每一個類只有一個,非靜態成員每一個對象一個
15.純虛函數如何定義?使用時應注意什麼? virtual void f()=0; 是接口,子類必需要實現
16.數組和鏈表的區別 數組:數據順序存儲,固定大小 連表:數據能夠隨機存儲,大小可動態改變
17.ISO的七層模型是什麼?tcp/udp是屬於哪一層?tcp/udp有何優缺點? 應用層 表示層 會話層 運輸層 網絡層 物理鏈路層 物理層 tcp /udp屬於運輸層 TCP 服務提供了數據流傳輸、可靠性、有效流控制、全雙工操做和多路複用技術等。 與 TCP 不一樣, UDP 並不提供對 IP 協議的可靠機制、流控制以及錯誤恢復功能等。因爲 UDP 比較簡單, UDP 頭包含不多的字節,比 TCP 負載消耗少。 tcp: 提供穩定的傳輸服務,有流量控制,缺點是包頭大,冗餘性很差 udp: 不提供穩定的服務,包頭小,開銷小
一、(void )ptr 和 ((void**))ptr的結果是否相同?其中ptr爲同一個指針 .(void )ptr 和 ((void**))ptr值是相同的
二、int main() { int x=3; printf("%d",x); return 1;
} 問函數既然不會被其它函數調用,爲何要返回1? mian中,c標準認爲0表示成功,非0表示錯誤。具體的值是某中具體出錯信息
三、要對絕對地址0x100000賦值,咱們能夠用 (unsigned int*)0x100000 = 1234; 那麼要是想讓程序跳轉到絕對地址是0x100000去執行,應該怎麼作? ((void ()( ))0x100000 ) ( ); 首先要將0x100000強制轉換成函數指針,即: (void ()())0x100000 而後再調用它: ((void ()())0x100000)(); 用typedef能夠看得更直觀些: typedef void()() voidFuncPtr; *((voidFuncPtr)0x100000)();
四、已知一個數組table,用一個宏定義,求出數據的元素個數 #define NTBL #define NTBL (sizeof(table)/sizeof(table[0]))
五、線程與進程的區別和聯繫? 線程是否具備相同的堆棧? dll是否有獨立的堆棧? 進程是死的,只是一些資源的集合,真正的程序執行都是線程來完成的,程序啓動的時候操做系統就幫你建立了一個主線程。 每一個線程有本身的堆棧。 DLL 中有沒有獨立的堆棧,這個問題很差回答,或者說這個問題自己是否有問題。由於DLL中的代碼是被某些線程所執行,只有線程擁有堆棧,若是DLL中的代碼是 EXE中的線程所調用,那麼這個時候是否是說這個DLL沒有本身獨立的堆棧?若是DLL中的代碼是由DLL本身建立的線程所執行,那麼是否是說DLL有獨立的堆棧?
以上講的是堆棧,若是對於堆來講,每一個DLL有本身的堆,因此若是是從DLL中動態分配的內存,最好是從DLL中刪除,若是你從DLL中分配內存,而後在EXE中,或者另一個DLL中刪除,頗有可能致使程序崩潰
6、unsigned short A = 10; printf("~A = %u\n", ~A);
char c=128; printf("c=%d\n",c);
輸出多少?並分析過程 第一題,~A =0xfffffff5,int值 爲-11,但輸出的是uint。因此輸出4294967285 第二題,c=0x10,輸出的是int,最高位爲1,是負數,因此它的值就是0x00的補碼就是128,因此輸出-128。 這兩道題都是在考察二進制向int或uint轉換時的最高位處理。
七、long a=0x801010; a+5=? 0x801010用二進制表示爲:「1000 0000 0001 0000 0001 0000」,十進制的值爲8392720,再加上5就是8392725
8、給定結構struct A { char t:4; char k:4; unsigned short i:8; unsigned long m; };問sizeof(A) = ? 給定結構struct A { char t:4; 4位 char k:4; 4位 unsigned short i:8; 8位 unsigned long m; // 偏移2字節保證4字節對齊 }; // 共8字節
9、下面的函數實如今一個數上加一個數,有什麼錯誤?請改正。 int add_n ( int n ) { static int i = 100; i += n; return i; } 當你第二次調用時得不到正確的結果,難道你寫個函數就是爲了調用一次?問題就出在 static上?
十、求函數返回值,輸入x=9999; int func ( x ) { int countx = 0; while ( x ) { countx ++; x = x&(x-1); } return countx; } 結果呢? 知道了這是統計9999的二進制數值中有多少個1的函數,且有 9999=9×1024+512+256+15
9×1024中含有1的個數爲2; 512中含有1的個數爲1; 256中含有1的個數爲1; 15中含有1的個數爲4; 故共有1的個數爲8,結果爲8。 1000 - 1 = 0111,正好是原數取反。這就是原理。 用這種方法來求1的個數是很效率很高的。 沒必要去一個一個地移位。循環次數最少。
十一、int a,b,c 請寫函數實現C=a+b ,不能夠改變數據類型,如將c改成long int,關鍵是如何處理溢出問題 bool add (int a, int b,int *c) { *c=a+b; return (a>0 && b>0 &&(*c<a || *c<b) || (a<0 && b<0 &&(*c>a || *c>b))); }
十二、分析: struct bit { int a:3; int b:2; int c:3; }; int main() { bit s; char c=(char)&s; cout<<sizeof(bit)<<endl; *c=0x99; cout << s.a <<endl <<s.b<<endl<<s.c<<endl; int a=-1; printf("%x",a); return 0; } 輸出爲何是 4 1 -1 -4 ffffffff 由於0x99在內存中表示爲 100 11 001 , a = 001, b = 11, c = 100 當c爲有符合數時, c = 100, 最高1爲表示c爲負數,負數在計算機用補碼錶示,因此c = -4;同理 b = -1; 當c爲有符合數時, c = 100,即 c = 4,同理 b = 3