读书笔记之知识杂点
1.x=x+1,x+1,x++,哪個效率最高?為什么?
x=x+1最低,因為它的執行過程如下:
(1)讀取右x的地址
(2)x+1
(3)讀取左x的地址
(4)將右值傳給左邊的x(編譯器并不認為左右的x的地址相同)
x+=1其次,其執行過程如下:
(1)讀取右x的地址
(2)x+1
(3)將得到的值傳給x(因為x的地址已經讀出)
x++效率最高,其執行過程如下
(1)讀取右x的地址
(2)x自增1
2.
?
#define?product(x)?(x*x)int?main()
{
???????int?i?=?3,j,k;
???????j?=?product(i++);
???????k?=?product(++i);
???????printf(“j?=?%d,k?=?%d",j,k);
???????return?0;??
}
輸出結果是什么?
product(i++) = i++*i++;i = 3,先取i計算,然后i自加2次,所以j等于9,此時i等于5.product(++i)要求先累加i,累積后i等于7,所以product(++i)的結果是49.
3.A://a is a variable
寫法1:
if(‘A’?==?a){
??????a++;
}
寫法2:
if(a?==?‘A’){
??????a++;
}
B:
寫法1:
for(i?=?0;i<8;i++){
?????X?=?i+Y+J*7;
?????printf(“%d”,X);?????
}
寫法2:
S?=?Y+J*7;for(i?=?0;i<8;i++)
{
?????printf(“%d”,i+S);?
}
A和B中各有兩種寫法,其中那一種寫法比較好?
A.寫法1好,'A’ == a,如果把"=="誤寫為"="的話,因為編譯器不允許對常量賦值,就可以檢查到錯誤。
B.寫法2好,將部分加法運算放到了循環體外,提高了效率。缺點是程序不夠簡潔。
3.
unsigned?int?a?=?3;int?b?=?–5;
(a+b>0)?a++:b++;
cout<<a<<endl;
cout<<b<<endl;
則輸出a,b的值為多少?
a = 4;
b = –5;
a是unsigned int型的,再與b相加時,b轉換為unsigned型的,故結果為4294967295而不是-2。
4.在C++程序中調用被C編譯器編譯后的函數,為什么要加extern “C”?
????? C++語言支持函數重載,C語言不支持函數重載。函數被C++編譯后在庫中的名字與C語言的不同。假設某個函數的原型為:void foo(int x,int y)。該函數被C編譯器編譯后在庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字。
????? C++提供了C連接交換指定符號extern “C” 解決名字匹配問題。
5.如何判斷一段程序是由C編譯程序還是由C++編譯程序編譯的?
C++編譯時定義了_cplusplus。
C編譯時定義了STDC。
6.main主函數執行完畢后,是否可能會在執行一段代碼?
如果需要加入一段在main退出后執行的代碼,可以使用atexit()函數注冊一個函數:
#include<iostream>?#include<stdlib.h>?
using?namespace?std;?
//int?atexit(void?(*function)(void));?
void?fun1(),fun2(),fun3(),fun4();?
int?main()?
{?
????atexit(fun1);?
????atexit(fun2);?
????atexit(fun3);?
????atexit(fun4);?
????printf("This?is?excute?first.\n");?
}?
void?fun1()?
{?
????printf("Next.\n");?
}?
void?fun2()?
{?
????printf("excute?");?
}?
void?fun3()?
{?
????printf("is?");?
}?
void?fun4()?
{?
????printf("This?");?
}
atexit()用來設置一個程序正常結束前調用的函數。當程序通過調用exit()或從main中返回時,參數function所指定的函數會先被調用,然后才真正由exit()結束程序。
如果執行成功則返回0,否則返回-1,失敗原因存于errno中。
7.宏定義,下面的代碼輸出結果是什么?
#define?SQR(x)?(x*x)main()
{
??????int?a,b=3;
??????a?=?SQR(b?+?2);
??????printf(“\n%d”,a);
}
結果應為11
宏定義展開時容易造成二義性問題。a = SQR(b + 2)這一語句展開后為"b + 2 * b + 2”,而不是想象中的"(b + 2)*(b + 2)"。要是先得到這個結果必須把宏定義語句改為如下的形式:
#define SQR(x) ((x)*(x))
這樣輸出的結果為25。
8.程序的輸出結果是什么?
#include?<iostream>using?namespace?std;
char*?GetMemory()
{
??????char?p[]?=?“Hello?world”;
??????return?p;
}
int?main()
{
??????char?*ch?=?NULL;
??????ch?=?GetMemory();
??????cout<<ch;
??????return?0;
}
程序輸出可能是亂碼,也可能正常輸出,因為GetMemory返回的是指向"棧內存"的指針,該指針的地址不是NULL,但其原來的內容已經被清除,新內容不可知。
9.函數指針:void (*p)()
函數返回指針:void * p()
const指針:const int *
指向const的指針:int * const
指向const的const指針:const int * const
10.int a[9] = {0,1,2,3,4,5,6,7,8};
int *p = a;
數組名代表數組的首地址,是一個常量指針,是不可以修改的,a++是錯誤的,p是個指針變量是可以修改的,如同時表示a[1]的話,可表示為*(a+1),*(p+1),*(++p)
11.
static?int?a[3][3]?=?{1,3,5,7,9,11,13,15,17},y,x,*p?=?&a[2][2];for(x?=?0;x<3;x++)
?????y?+=?*(p?–?4?*?x);
printf(“\n%d”,y);
輸出結果是什么?
27,三次循環相加的數分別為17 + 9 + 1,p - n相當于p的地址減去n*4(整型類型的大小).
12.float (**def)[10]
def是一個二級指針,它指向的是一個一維數組的指針,數組的元素都是float。
double *(*gh)[10]
gh是一個指針,它指向一個一維數組,數組元素都是double*。
double (*f[10])()
f是一個數組,f有10個元素,元素都是函數的指針,指向的函數類型是沒有參數且返回double的函數。
int *((*b)[10])
就跟"int *(*b)[10]”是一樣的,b是一維數組的指針。
Long (*fun)(int)
函數指針。
int (*(*F)(int,int))(int)
F是一個函數的指針,指向的函數的類型是有兩個int參數并且返回一個函數指針的函數,返回的函數指針指向又一個int參數且返回int的函數。
13.句柄地址(穩定)->記載著對象在內存中的地址->對象在內存中的地址(不穩定)->實際對象。
14.一個射擊運動員打靶,靶一共有10環,連開10槍打中90環的可能性有多少種?使用遞歸實現
#include?<iostream>?using?namespace?std;?
int?sum;?
int?store[10];?
void?Output()?
{?
????for(int?i?=?9;i>=0;--i)?
????{?
????????cout<<store[i]<<"?";?
????}?
????cout<<endl;?
????++sum;?
}?
void?Cumput(int?score,int?num)?
{?
????if(score<0||score>(num+1)*10)?
????{?
????????return?;?
????}?
????if(num?==?0)?
????{?
????????store[num]?=?score;?
????????Output();?
????????return?;?
????}?
????for(int?i?=?0;i<=10;i++)?
????{?
????????store[num]?=?i;?
????????Cumput(score?-?i,num?-?1);?
????}?
}?
int?main()?
{?
????Cumput(90,9);?
????cout<<"總數:"<<sum<<endl;?
????return?0;?
}
15.C++中空類默認產生那些類成員函數?
構造函數、析構函數、賦值函數、拷貝構造函數。
16.
#include<iostream>using?namespace?std;
class?A
{
public:
???????void?virtual?f()
???????{
??????????????cout<<”A”<<endl;
???????}
};
class?B:public?A
{
public:
???????void?virtual?f()
???????{
??????????????cout<<”B”<<endl;
???????}
};
int?main()
{
???????A*?pa?=?new?A();
???????pa->f();
???????B*?pb?=?(B*)pa;
???????pb->f();
???????delete?pa,pb;
???????pa?=?new?B();
???????pa->f();
???????pb?=?(B*)pa;
???????pb->f();
???????return?0;
}
程序輸出A A B B
????? 這是一個虛函數覆蓋虛函數的問題。A類里的f函數是一個虛函數,虛函數是被子類同名函數所覆蓋的。而B類里的f函數也是一個虛函數,它覆蓋A類f函數的同時,也會被它的子類覆蓋。但是在B* pb = (B*)pa;里面,該語句的意思是轉化pa為B類型并新建一個指針pb,將pa復制到pb,但這里有一點請注意,就是pa的指針始終沒有發生變化。所以pb也指向pa的f函數。這里并不存在覆蓋的問題。
????? delete pa,pb;刪除了pa和pb所指向的地址,但pa,pb指針并沒有刪除,也就是我們通常所說的懸浮指針?,F在重新給pa指向新地址,所指向的位置是B類的,而pa指針類型是A類的,所以就產生了一個覆蓋。pa->f();的值是B。
????? pb = (B*)pa;轉化pa為B類指針給pb賦值,但pa所指向的f函數是B類的f函數,所以pb所指向的f函數是B類的f函數。pb->f();的值是B。
17.我們知道,大多數主流的語言或運行環境都支持3種最基本的內存分配方式,他們分別是:
靜態分配:靜態變量和全局變量的分配形式。我們可以把靜態分配的內存看成是家里的耐用家具。通常,他們無需釋放和回收,因為沒有人會天天把大衣柜當做垃圾扔到窗外。
自動分配:在棧中為局部變量分配內存的方法,棧中的內存可以隨著代碼塊退出時的出棧操作被自動釋放。這類似于到家中串門的訪客,天色一晚就要各自回各家,除了個別不識時務者以外,我們一般沒必要把客人捆在垃圾袋里掃地出門。
動態分配:在堆中動態分配內存空間以存儲數據的方式。堆中的內存塊好像我們日常使用的餐巾紙,用過了就得扔到垃圾箱里,否則屋內就會滿地狼藉。像我這樣的懶人做夢都想有一臺家用機器人跟在身邊打掃衛生。在軟件開發中,如果你懶得釋放內存,那么你也需要一臺類似的機器人——這其實就是一個有特定算法實現的垃圾收集器。
18.OSI七層模型
1>.物理層涉及到在信道上傳輸的原始比特流
2>.數據鏈路層的主要任務是加強物理層傳輸原始比特流的功能,使之對應的網絡層顯現為一條無錯線路。發送包把輸入數據封裝在數據幀,按順序傳送出去并處理接受方回送的確認幀。
3>.網絡層關系到子網的運行控制,其中一個關鍵問題是確認從源端到目的端如何選擇路由。
4>.傳輸層的基本功能是從會話層接受數據而且把其分成較小的單元傳遞給網絡層。
5>.會話層允許不同機器上的用戶建立會話關系。
6>.表示層用來完成某些特定的功能。
7>.應用層包含著大量人們普遍需要的協議。
19.存儲過程和函數的區別是什么?
存儲過程是用戶定義的一系列SQL語句的集合,涉及特定表或其他對象的任務,用戶可以調用存儲過程。而函數通常是數據庫已定義的方法,它接受參數并返回某種類型的值,并且不涉及特定用戶表。
游標的作用是什么?如何知道游標已經到了最后?
游標用于定位結果集的行。通過判斷全局變量@@FETCH_STATUS可以判斷其是否到了最后。通過此變量不等于0表示出錯或到了最后。
20.多維數組和指針
char?a[3][4];?char?(*p)[4];?
char?*p1?
char?**p2;?
p?=?a;?//正確?
p1?=?*a;?//正確?
p2?=?a;?//錯誤?
a是一個二維數組名,一個指向一維數組的指針
p是一個指向含有4個元素的一維數組的指針
p1是一個指向字符型變量的指針,*a相當于a[0],而a[0]是一個一維數組名,代表一維數組首元素的地址即&a[0][0],a[0][0]是一個字符型變量,所以正確
p2是一個指向字符型指針的指針
?
轉載于:https://www.cnblogs.com/wanghao111/archive/2009/09/11/1564912.html
總結
- 上一篇: undefined reference
- 下一篇: 超市购物打印小票的简单程序 记录下来