青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

asm, c, c++ are my all
-- Core In Computer
posts - 139,  comments - 123,  trackbacks - 0
     摘要: 在向大家介紹CxImage類庫之前,先向大家推薦一個(gè)優(yōu)秀的站點(diǎn): http://www.codeproject.com 。這個(gè)站點(diǎn)有很多值得收藏的文章和源碼。本文就是根據(jù)此站點(diǎn)相關(guān)信息寫成。 關(guān)于這個(gè)類,可以看CodeProject上的文章:http://www.codeproject.com/bi...  閱讀全文
posted @ 2006-09-10 21:07 Jerry Cat 閱讀(1302) | 評論 (0)編輯 收藏

[c++語言]goto語句中標(biāo)記(labels)的使用
goto語句可以將程序控制轉(zhuǎn)移到由“標(biāo)記”所指定的地方,這是地球人都知道的。

關(guān)于標(biāo)記的用法不太知道或沒注意的地方:
1。標(biāo)記不能單獨(dú)出現(xiàn),必須后跟一條語句;如果需要一個(gè)單獨(dú)的標(biāo)記(想不出有這種需要),則在標(biāo)記后放一條空語句。
2。標(biāo)記在它所在的函數(shù)內(nèi)有效,不能重新定義。不同函數(shù)中可以使用同名標(biāo)記。

reference:
ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/vclang/html/_pluslang_Using_Labels_with_the_goto_Statement.htm

posted @ 2006-09-10 21:01 Jerry Cat 閱讀(1685) | 評論 (0)編輯 收藏
猶太諺語:父親幫助兒子時(shí),兩人都笑了;兒子幫助父親時(shí),兩人都哭了。
猶太諺語:一個(gè)傻子丟了一顆石頭到池塘里,十個(gè)聰明人也檢不回來!
猶太諺語:財(cái)富就在一碼之內(nèi)。
猶太諺語:人生有三種東西會傷人:苦惱、爭吵和空的錢包。
猶太諺語:投資自己陌生的行業(yè)的人,都將與黃金失之交臂。
posted @ 2006-09-10 20:41 Jerry Cat 閱讀(508) | 評論 (0)編輯 收藏

C++面試題

1.是不是一個(gè)父類寫了一個(gè)virtual 函數(shù),如果子類覆蓋它的函數(shù)不加virtual ,也能實(shí)現(xiàn)多態(tài)?

virtual修飾符會被隱形繼承的。

private 也被集成,只事派生類沒有訪問權(quán)限而已

virtual可加可不加

子類的空間里有父類的所有變量(static除外)

同一個(gè)函數(shù)只存在一個(gè)實(shí)體(inline除外)

子類覆蓋它的函數(shù)不加virtual ,也能實(shí)現(xiàn)多態(tài)。

在子類的空間里,有父類的私有變量。私有變量不能直接訪問。


--------------------------------------------------------------------------
2.輸入一個(gè)字符串,將其逆序后輸出。(使用C++,不建議用偽碼)

#include <iostream>
using namespace std;


void main()
{
? char a[50];memset(a,0,sizeof(a));
? int i=0,j;
? char t;
? cin.getline(a,50,'\n');
? for(i=0,j=strlen(a)-1;i<strlen(a)/2;i++,j--)
? {
?? t=a[i];
????? a[i]=a[j];
?? a[j]=t;
? }
? cout<<a<<endl;?
}

//第二種

string str;
cin>>str;
str.replace;
cout<<str;


--------------------------------------------------------------------------
3.請簡單描述Windows內(nèi)存管理的方法。

內(nèi)存管理是操作系統(tǒng)中的重要部分,兩三句話恐怕誰也說不清楚吧~~
我先說個(gè)大概,希望能夠拋磚引玉吧

當(dāng)程序運(yùn)行時(shí)需要從內(nèi)存中讀出這段程序的代碼。代碼的位置必須在物理內(nèi)存中才能被運(yùn)行,由于現(xiàn)在的操作系統(tǒng)中有非常多的程序運(yùn)行著,內(nèi)存中不能夠完全放下,所以引出了虛擬內(nèi)存的概念。把哪些不常用的程序片斷就放入虛擬內(nèi)存,當(dāng)需要用到它的時(shí)候在load入主存(物理內(nèi)存)中。這個(gè)就是內(nèi)存管理所要做的事。內(nèi)存管理還有另外一件事需要做:計(jì)算程序片段在主存中的物理位置,以便CPU調(diào)度。

內(nèi)存管理有塊式管理,頁式管理,段式和段頁式管理。現(xiàn)在常用段頁式管理

塊式管理:把主存分為一大塊、一大塊的,當(dāng)所需的程序片斷不在主存時(shí)就分配一塊主存空間,把程 序片斷l(xiāng)oad入主存,就算所需的程序片度只有幾個(gè)字節(jié)也只能把這一塊分配給它。這樣會造成很大的浪費(fèi),平均浪費(fèi)了50%的內(nèi)存空間,但時(shí)易于管理。

頁式管理:把主存分為一頁一頁的,每一頁的空間要比一塊一塊的空間小很多,顯然這種方法的空間利用率要比塊式管理高很多。

段式管理:把主存分為一段一段的,每一段的空間又要比一頁一頁的空間小很多,這種方法在空間利用率上又比頁式管理高很多,但是也有另外一個(gè)缺點(diǎn)。一個(gè)程序片斷可能會被分為幾十段,這樣很多時(shí)間就會被浪費(fèi)在計(jì)算每一段的物理地址上(計(jì)算機(jī)最耗時(shí)間的大家都知道是I/O吧)。

段頁式管理:結(jié)合了段式管理和頁式管理的優(yōu)點(diǎn)。把主存分為若干頁,每一頁又分為若干段。好處就很明顯,不用我多說了吧。

各種內(nèi)存管理都有它自己的方法來計(jì)算出程序片斷在主存中的物理地址,其實(shí)都很相似。

這只是一個(gè)大概而已,不足以說明內(nèi)存管理的皮毛。無論哪一本操作系統(tǒng)書上都有詳細(xì)的講解


--------------------------------------------------------------------------
4.
#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);

?return 0;
}
這道題目的結(jié)果是什么啊?

define 只是定義而已,在編擇時(shí)只是簡單代換X*X而已,并不經(jīng)過算術(shù)法則的

a /= (k+m)*(k+m)/(k+m)*(k+m);
=>a /= (k+m)*1*(k+m);
=>a = a/9;
=>a = 1;

--------------------------------------------------------------------------
5.
const 符號常量;
(1)const char *p
(2)char const *p
(3)char * const p
說明上面三種描述的區(qū)別;


如果const位于星號的左側(cè),則const就是用來修飾指針?biāo)赶虻淖兞浚粗羔樦赶驗(yàn)槌A浚?br />如果const位于星號的右側(cè),const就是修飾指針本身,即指針本身是常量。

(1)const char *p

一個(gè)指向char類型的const對象指針,p不是常量,我們可以修改p的值,使其指向不同的char,但是不能改變它指向非char對象,如:
const char *p;
char c1='a';
char c2='b';
p=&c1;//ok
p=&c2;//ok
*p=c1;//error

(2)char const *p
(3)char * const p

這兩個(gè)好象是一樣的,此時(shí)*p可以修改,而p不能修改。

(4)const char * const p
這種是地址及指向?qū)ο蠖疾荒苄薷摹?/font>

--------------------------------------------------------------------------
6.下面是C語言中兩種if語句判斷方式。請問哪種寫法更好?為什么?
?int n;
?if (n == 10) // 第一種判斷方式
?if (10 == n) // 第二種判斷方式

如果少了個(gè)=號,編譯時(shí)就會報(bào)錯,減少了出錯的可能行,可以檢測出是否少了=

--------------------------------------------------------------------------
7.下面的代碼有什么問題?
void DoSomeThing(...)
{
?char* p;
?...
?p = malloc(1024);? // 分配1K的空間
?if (NULL == p)
? return;
?...
?p = realloc(p, 2048); // 空間不夠,重新分配到2K
?if (NULL == p)
? return;
?...
}

A:
p = malloc(1024);???? 應(yīng)該寫成: p = (char *) malloc(1024);
??????? 沒有釋放p的空間,造成內(nèi)存泄漏。


--------------------------------------------------------------------------
8.下面的代碼有什么問題?并請給出正確的寫法。
void DoSomeThing(char* p)
{
?char str[16];
?int n;
?assert(NULL != p);
?sscanf(p, "%s%d", str, n);
?if (0 == strcmp(str, "something"))
?{
? ...
?}
}

A:
sscanf(p, "%s%d", str, n);?? 這句該寫成: sscanf(p, "%s%d", str, &n);

--------------------------------------------------------------------------
9.下面代碼有什么錯誤?
Void test1()
{
?char string[10];
?char *str1="0123456789";
?strcpy(string, str1);
}

數(shù)組越界

--------------------------------------------------------------------------
10.下面代碼有什么問題?
Void test2()
{
? char string[10], str1[10];
? for(i=0; i<10;i++)
? {
???? str1[i] ='a';
? }
? strcpy(string, str1);
}

數(shù)組越界

--------------------------------------------------------------------------
11.下面代碼有什么問題?
Void test3(char* str1)
{
? char string[10];
? if(strlen(str1)<=10)
? {
??? strcpy(string, str1);
? }
}

==數(shù)組越界
==strcpy拷貝的結(jié)束標(biāo)志是查找字符串中的\0 因此如果字符串中沒有遇到\0的話 會一直復(fù)制,直到遇到\0,上面的123都因此產(chǎn)生越界的情況
?
建議使用 strncpy 和 memcpy

--------------------------------------------------------------------------
12.下面代碼有什么問題?

#define MAX_SRM 256

DSN get_SRM_no()
{
? static int SRM_no; //是不是這里沒賦初值?
? int I;
? for(I=0;I<MAX_SRM;I++,SRM_no++)
? {
??? SRM_no %= MAX_SRM;
??? if(MY_SRM.state==IDLE)
??? {
????? break;
??? }
? }
? if(I>=MAX_SRM)
??? return (NULL_SRM);
? else
??? return SRM_no;
}

系統(tǒng)會初始化static int變量為0,但該值會一直保存,所謂的不可重入...

--------------------------------------------------------------------------
13.寫出運(yùn)行結(jié)果:
{// test1
??? char str[] = "world"; cout << sizeof(str) << ": ";
??? char *p??? = str;???? cout << sizeof(p) << ": ";
??? char i???? = 10;????? cout << sizeof(i) << ": ";
??? void *pp?? = malloc(10);? cout << sizeof(p) << endl;
}

6:4:1:4

--------------------------------------------------------------------------
14.寫出運(yùn)行結(jié)果:
{// test2
??? union V {
?struct X {
? unsigned char s1:2;
? unsigned char s2:3;
? unsigned char s3:3;
?} x;

?unsigned char c;
??? } v;

??? v.c = 100;
??? printf("%d", v.x.s3);

}

3

--------------------------------------------------------------------------
15.用C++寫個(gè)程序,如何判斷一個(gè)操作系統(tǒng)是16位還是32位的?不能用sizeof()函數(shù)

A1:
16位的系統(tǒng)下,
int i = 65536;
cout << i; // 輸出0;
int i = 65535;
cout << i; // 輸出-1;

32位的系統(tǒng)下,
int i = 65536;
cout << i; // 輸出65536;
int i = 65535;
cout << i; // 輸出65535;

A2:

int a = ~0;
if( a>65536 )
{
??? cout<<"32 bit"<<endl;
}
else
{
??? cout<<"16 bit"<<endl;
}


--------------------------------------------------------------------------
16.C和C++有什么不同?

從機(jī)制上:c是面向過程的(但c也可以編寫面向?qū)ο蟮某绦颍籧++是面向?qū)ο蟮模峁┝祟悺5牵?br />c++編寫面向?qū)ο蟮某绦虮萩容易

從適用的方向:c適合要求代碼體積小的,效率高的場合,如嵌入式;c++適合更上層的,復(fù)雜的;? llinux核心大部分是c寫的,因?yàn)樗窍到y(tǒng)軟件,效率要求極高。

從名稱上也可以看出,c++比c多了+,說明c++是c的超集;那為什么不叫c+而叫c++呢,是因?yàn)閏++比
c來說擴(kuò)充的東西太多了,所以就在c后面放上兩個(gè)+;于是就成了c++

C語言是結(jié)構(gòu)化編程語言,C++是面向?qū)ο缶幊陶Z言。
C++側(cè)重于對象而不是過程,側(cè)重于類的設(shè)計(jì)而不是邏輯的設(shè)計(jì)。

--------------------------------------------------------------------------
17.在不用第三方參數(shù)的情況下,交換兩個(gè)參數(shù)的值
#include <stdio.h>

void main()
{
??????? int i=60;
??????? int j=50;
??????? i=i+j;
??????? j=i-j;
??????? i=i-j;
??????? printf("i=%d\n",i);
??????? printf("j=%d\n",j);
}

方法二:
i^=j;
j^=i;
i^=j;

方法三:
// 用加減實(shí)現(xiàn),而且不會溢出
a = a+b-(b=a)

--------------------------------------------------------------------------
18.有關(guān)位域的面試題(為什么輸出的是一個(gè)奇怪的字符)

a.t = 'b';效果相當(dāng)于 a.t= 'b' & 0xf;

'b' --> 01100010
'b' & 0xf -->>00000010
所以輸出Ascii碼為2的特殊字符


char t:4;就是4bit的字符變量,同樣
unsigned short i:8;就是8bit的無符號短整形變量

--------------------------------------------------------------------------
19.int i=10, j=10, k=3; k*=i+j; k最后的值是?

60

--------------------------------------------------------------------------
20.進(jìn)程間通信的方式有?

進(jìn)程間通信的方式有 共享內(nèi)存, 管道 ,Socket ,消息隊(duì)列 , DDE等

--------------------------------------------------------------------------
21.
struct A
{
char t:4;
char k:4;
unsigned short i:8;
unsigned long m;
}
sizeof(A)=?(不考慮邊界對齊)

7

struct CELL???????????? // Declare CELL bit field
{
?? unsigned character? : 8;? // 00000000 ????????
?? unsigned foreground : 3;? // 00000??? 00000000
?? unsigned intensity? : 1;? // 0000?000 00000000
?? unsigned background : 3;? // 0???0000 00000000
?? unsigned blink????? : 1;? // ?0000000 00000000
} screen[25][80];?????? // Array of bit fields
二、位結(jié)構(gòu)
??? 位結(jié)構(gòu)是一種特殊的結(jié)構(gòu), 在需按位訪問一個(gè)字節(jié)或字的多個(gè)位時(shí), 位結(jié)構(gòu)
比按位運(yùn)算符更加方便。
??? 位結(jié)構(gòu)定義的一般形式為:
???? struct位結(jié)構(gòu)名{
????????? 數(shù)據(jù)類型 變量名: 整型常數(shù);
????????? 數(shù)據(jù)類型 變量名: 整型常數(shù);
???? } 位結(jié)構(gòu)變量;
??? 其中: 數(shù)據(jù)類型必須是int(unsigned或signed)。 整型常數(shù)必須是非負(fù)的整
數(shù), 范圍是0~15, 表示二進(jìn)制位的個(gè)數(shù), 即表示有多少位。
??? 變量名是選擇項(xiàng), 可以不命名, 這樣規(guī)定是為了排列需要。
??? 例如: 下面定義了一個(gè)位結(jié)構(gòu)。
???? struct{
????????? unsigned incon: 8;? /*incon占用低字節(jié)的0~7共8位*/
????????? unsigned txcolor: 4;/*txcolor占用高字節(jié)的0~3位共4位*/
????????? unsigned bgcolor: 3;/*bgcolor占用高字節(jié)的4~6位共3位*/
????????? unsigned blink: 1;? /*blink占用高字節(jié)的第7位*/
???? }ch;
??? 位結(jié)構(gòu)成員的訪問與結(jié)構(gòu)成員的訪問相同。
??? 例如: 訪問上例位結(jié)構(gòu)中的bgcolor成員可寫成:
????? ch.bgcolor
?
??? 注意:
??? 1. 位結(jié)構(gòu)中的成員可以定義為unsigned, 也可定義為signed,? 但當(dāng)成員長
度為1時(shí), 會被認(rèn)為是unsigned類型。因?yàn)閱蝹€(gè)位不可能具有符號。
??? 2. 位結(jié)構(gòu)中的成員不能使用數(shù)組和指針, 但位結(jié)構(gòu)變量可以是數(shù)組和指針,
如果是指針, 其成員訪問方式同結(jié)構(gòu)指針。
??? 3. 位結(jié)構(gòu)總長度(位數(shù)), 是各個(gè)位成員定義的位數(shù)之和,? 可以超過兩個(gè)字
節(jié)。
??? 4. 位結(jié)構(gòu)成員可以與其它結(jié)構(gòu)成員一起使用。
??? 例如:
???? struct info{
????????? char name[8];
????????? int age;
????????? struct addr address;
????????? float pay;
????????? unsigned state: 1;
????????? unsigned pay: 1;
????????? }workers;
??? 上例的結(jié)構(gòu)定義了關(guān)于一個(gè)工人的信息。其中有兩個(gè)位結(jié)構(gòu)成員, 每個(gè)位結(jié)
構(gòu)成員只有一位, 因此只占一個(gè)字節(jié)但保存了兩個(gè)信息, 該字節(jié)中第一位表示工
人的狀態(tài), 第二位表示工資是否已發(fā)放。由此可見使用位結(jié)構(gòu)可以節(jié)省存貯空間。


--------------------------------------------------------------------------
22.下面的函數(shù)實(shí)現(xiàn)在一個(gè)固定的數(shù)上加上一個(gè)數(shù),有什么錯誤,改正
int add_n(int n)
{
? static int i=100;
? i+=n;
? return i;
}

答:
因?yàn)閟tatic使得i的值會保留上次的值。
去掉static就可了

--------------------------------------------------------------------------
23.下面的代碼有什么問題?
class A
{
public:
? A() { p=this; }
? ~A() { if(p!=NULL) { delete p; p=NULL; } }

? A* p;
};

答:
會引起無限遞歸

--------------------------------------------------------------------------
24.
union a {
?int a_int1;
?double a_double;
?int a_int2;
};

typedef struct
{
?a a1;
?char y;
} b;

class c
{
?double c_double;
?b b1;
?a a2;

};

輸出cout<<sizeof(c)<<endl;的結(jié)果?

答:
VC6環(huán)境下得出的結(jié)果是32

另:
我(sun)在VC6.0+win2k下做過試驗(yàn):
short - 2
int-4
float-4
double-8
指針-4

sizeof(union),以結(jié)構(gòu)里面size最大的為union的size

解析C語言中的sizeof

一、sizeof的概念 
  sizeof是C語言的一種單目操作符,如C語言的其他操作符++、--等。它并不是函數(shù)。sizeof操作符以字節(jié)形式給出了其操作數(shù)的存儲大小。操作數(shù)可以是一個(gè)表達(dá)式或括在括號內(nèi)的類型名。操作數(shù)的存儲大小由操作數(shù)的類型決定。 

二、sizeof的使用方法 
  1、用于數(shù)據(jù)類型 

  sizeof使用形式:sizeof(type) 

  數(shù)據(jù)類型必須用括號括住。如sizeof(int)。 

  2、用于變量 

  sizeof使用形式:sizeof(var_name)或sizeof var_name 

  變量名可以不用括號括住。如sizeof (var_name),sizeof var_name等都是正確形式。帶括號的用法更普遍,大多數(shù)程序員采用這種形式。 

  注意:sizeof操作符不能用于函數(shù)類型,不完全類型或位字段。不完全類型指具有未知存儲大小的數(shù)據(jù)類型,如未知存儲大小的數(shù)組類型、未知內(nèi)容的結(jié)構(gòu)或聯(lián)合類型、void類型等。 

  如sizeof(max)若此時(shí)變量max定義為int max(),sizeof(char_v) 若此時(shí)char_v定義為char char_v [MAX]且MAX未知,sizeof(void)都不是正確形式。 

三、sizeof的結(jié)果 
  sizeof操作符的結(jié)果類型是size_t,它在頭文件

中typedef為unsigned int類型。該類型保證能容納實(shí)現(xiàn)所建立的最大對象的字節(jié)大小。 

  1、若操作數(shù)具有類型char、unsigned char或signed char,其結(jié)果等于1。 

  ANSI C正式規(guī)定字符類型為1字節(jié)。 

  2、int、unsigned int 、short int、unsigned short 、long int 、unsigned long 、 float、double、long double類型的sizeof 在ANSI C中沒有具體規(guī)定,大小依賴于實(shí)現(xiàn),一般可能分別為2、2、2、2、 4、4、4、8、10。 

  3、當(dāng)操作數(shù)是指針時(shí),sizeof依賴于編譯器。例如Microsoft C/C++7.0中,near類指針字節(jié)數(shù)為2,far、huge類指針字節(jié)數(shù)為4。一般Unix的指針字節(jié)數(shù)為4。 

  4、當(dāng)操作數(shù)具有數(shù)組類型時(shí),其結(jié)果是數(shù)組的總字節(jié)數(shù)。 

  5、聯(lián)合類型操作數(shù)的sizeof是其最大字節(jié)成員的字節(jié)數(shù)。結(jié)構(gòu)類型操作數(shù)的sizeof是這種類型對象的總字節(jié)數(shù),包括任何墊補(bǔ)在內(nèi)。 

  讓我們看如下結(jié)構(gòu): 

  struct {char b; double x;} a; 

  在某些機(jī)器上sizeof(a)=12,而一般sizeof(char)+ sizeof(double)=9。 

  這是因?yàn)榫幾g器在考慮對齊問題時(shí),在結(jié)構(gòu)中插入空位以控制各成員對象的地址對齊。如double類型的結(jié)構(gòu)成員x要放在被4整除的地址。 

  6、如果操作數(shù)是函數(shù)中的數(shù)組形參或函數(shù)類型的形參,sizeof給出其指針的大小。 

四、sizeof與其他操作符的關(guān)系 
  sizeof的優(yōu)先級為2級,比/、%等3級運(yùn)算符優(yōu)先級高。它可以與其他操作符一起組成表達(dá)式。如i*sizeof(int);其中i為int類型變量。 

五、sizeof的主要用途 
  1、sizeof操作符的一個(gè)主要用途是與存儲分配和I/O系統(tǒng)那樣的例程進(jìn)行通信。例如: 

  void *malloc(size_t size), 

  size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)。 

  2、sizeof的另一個(gè)的主要用途是計(jì)算數(shù)組中元素的個(gè)數(shù)。例如: 

  void * memset(void * s,int c,sizeof(s))。 

六、建議 
  由于操作數(shù)的字節(jié)數(shù)在實(shí)現(xiàn)時(shí)可能出現(xiàn)變化,建議在涉及到操作數(shù)字節(jié)大小時(shí)用sizeof來代替常量計(jì)算。


=============================================================
本文主要包括二個(gè)部分,第一部分重點(diǎn)介紹在VC中,怎么樣采用sizeof來求結(jié)構(gòu)的大小,以及容易出現(xiàn)的問題,并給出解決問題的方法,第二部分總結(jié)出VC中sizeof的主要用法。

1、 sizeof應(yīng)用在結(jié)構(gòu)上的情況

請看下面的結(jié)構(gòu):

struct MyStruct

{

double dda1;

char dda;

int type

};

對結(jié)構(gòu)MyStruct采用sizeof會出現(xiàn)什么結(jié)果呢?sizeof(MyStruct)為多少呢?也許你會這樣求:

sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13

但是當(dāng)在VC中測試上面結(jié)構(gòu)的大小時(shí),你會發(fā)現(xiàn)sizeof(MyStruct)為16。你知道為什么在VC中會得出這樣一個(gè)結(jié)果嗎?

其實(shí),這是VC對變量存儲的一個(gè)特殊處理。為了提高CPU的存儲速度,VC對一些變量的起始地址做了"對齊"處理。在默認(rèn)情況下,VC規(guī)定各成員變量存放的起始地址相對于結(jié)構(gòu)的起始地址的偏移量必須為該變量的類型所占用的字節(jié)數(shù)的倍數(shù)。下面列出常用類型的對齊方式(vc6.0,32位系統(tǒng))。

類型
對齊方式(變量存放的起始地址相對于結(jié)構(gòu)的起始地址的偏移量)

Char
偏移量必須為sizeof(char)即1的倍數(shù)

int
偏移量必須為sizeof(int)即4的倍數(shù)

float
偏移量必須為sizeof(float)即4的倍數(shù)

double
偏移量必須為sizeof(double)即8的倍數(shù)

Short
偏移量必須為sizeof(short)即2的倍數(shù)


各成員變量在存放的時(shí)候根據(jù)在結(jié)構(gòu)中出現(xiàn)的順序依次申請空間,同時(shí)按照上面的對齊方式調(diào)整位置,空缺的字節(jié)VC會自動填充。同時(shí)VC為了確保結(jié)構(gòu)的大小為結(jié)構(gòu)的字節(jié)邊界數(shù)(即該結(jié)構(gòu)中占用最大空間的類型所占用的字節(jié)數(shù))的倍數(shù),所以在為最后一個(gè)成員變量申請空間后,還會根據(jù)需要自動填充空缺的字節(jié)。

下面用前面的例子來說明VC到底怎么樣來存放結(jié)構(gòu)的。

struct MyStruct

{

double dda1;

char dda;

int type

};

為上面的結(jié)構(gòu)分配空間的時(shí)候,VC根據(jù)成員變量出現(xiàn)的順序和對齊方式,先為第一個(gè)成員dda1分配空間,其起始地址跟結(jié)構(gòu)的起始地址相同(剛好偏移量0剛好為sizeof(double)的倍數(shù)),該成員變量占用sizeof(double)=8個(gè)字節(jié);接下來為第二個(gè)成員dda分配空間,這時(shí)下一個(gè)可以分配的地址對于結(jié)構(gòu)的起始地址的偏移量為8,是sizeof(char)的倍數(shù),所以把dda存放在偏移量為8的地方滿足對齊方式,該成員變量占用 sizeof(char)=1個(gè)字節(jié);接下來為第三個(gè)成員type分配空間,這時(shí)下一個(gè)可以分配的地址對于結(jié)構(gòu)的起始地址的偏移量為9,不是sizeof (int)=4的倍數(shù),為了滿足對齊方式對偏移量的約束問題,VC自動填充3個(gè)字節(jié)(這三個(gè)字節(jié)沒有放什么東西),這時(shí)下一個(gè)可以分配的地址對于結(jié)構(gòu)的起始地址的偏移量為12,剛好是sizeof(int)=4的倍數(shù),所以把type存放在偏移量為12的地方,該成員變量占用sizeof(int)=4個(gè)字節(jié);這時(shí)整個(gè)結(jié)構(gòu)的成員變量已經(jīng)都分配了空間,總的占用的空間大小為:8+1+3+4=16,剛好為結(jié)構(gòu)的字節(jié)邊界數(shù)(即結(jié)構(gòu)中占用最大空間的類型所占用的字節(jié)數(shù)sizeof(double)=8)的倍數(shù),所以沒有空缺的字節(jié)需要填充。所以整個(gè)結(jié)構(gòu)的大小為:sizeof(MyStruct)=8+1+ 3+4=16,其中有3個(gè)字節(jié)是VC自動填充的,沒有放任何有意義的東西。

下面再舉個(gè)例子,交換一下上面的MyStruct的成員變量的位置,使它變成下面的情況:

struct MyStruct

{

char dda;

double dda1;??

int type

};

這個(gè)結(jié)構(gòu)占用的空間為多大呢?在VC6.0環(huán)境下,可以得到sizeof(MyStruc)為24。結(jié)合上面提到的分配空間的一些原則,分析下VC怎么樣為上面的結(jié)構(gòu)分配空間的。(簡單說明)

struct MyStruct

{

? char dda;//偏移量為0,滿足對齊方式,dda占用1個(gè)字節(jié);

double dda1;//下一個(gè)可用的地址的偏移量為1,不是sizeof(double)=8

???????????? //的倍數(shù),需要補(bǔ)足7個(gè)字節(jié)才能使偏移量變?yōu)?(滿足對齊

???????????? //方式),因此VC自動填充7個(gè)字節(jié),dda1存放在偏移量為8

???????????? //的地址上,它占用8個(gè)字節(jié)。

int type;//下一個(gè)可用的地址的偏移量為16,是sizeof(int)=4的倍

?????????? //數(shù),滿足int的對齊方式,所以不需要VC自動填充,type存

?????????? //放在偏移量為16的地址上,它占用4個(gè)字節(jié)。

};//所有成員變量都分配了空間,空間總的大小為1+7+8+4=20,不是結(jié)構(gòu)

?? //的節(jié)邊界數(shù)(即結(jié)構(gòu)中占用最大空間的類型所占用的字節(jié)數(shù)sizeof

?? //(double)=8)的倍數(shù),所以需要填充4個(gè)字節(jié),以滿足結(jié)構(gòu)的大小為

?? //sizeof(double)=8的倍數(shù)。


所以該結(jié)構(gòu)總的大小為:sizeof(MyStruc)為1+7+8+4+4=24。其中總的有7+4=11個(gè)字節(jié)是VC自動填充的,沒有放任何有意義的東西。


VC對結(jié)構(gòu)的存儲的特殊處理確實(shí)提高CPU存儲變量的速度,但是有時(shí)候也帶來了一些麻煩,我們也屏蔽掉變量默認(rèn)的對齊方式,自己可以設(shè)定變量的對齊方式。

VC 中提供了#pragma pack(n)來設(shè)定變量以n字節(jié)對齊方式。n字節(jié)對齊就是說變量存放的起始地址的偏移量有兩種情況:第一、如果n大于等于該變量所占用的字節(jié)數(shù),那么偏移量必須滿足默認(rèn)的對齊方式,第二、如果n小于該變量的類型所占用的字節(jié)數(shù),那么偏移量為n的倍數(shù),不用滿足默認(rèn)的對齊方式。結(jié)構(gòu)的總大小也有個(gè)約束條件,分下面兩種情況:如果n大于所有成員變量類型所占用的字節(jié)數(shù),那么結(jié)構(gòu)的總大小必須為占用空間最大的變量占用的空間數(shù)的倍數(shù);?

否則必須為n的倍數(shù)。下面舉例說明其用法。

#pragma pack(push) //保存對齊狀態(tài)

#pragma pack(4)//設(shè)定為4字節(jié)對齊

struct test

{

? char m1;

? double m4;

? int? m3;

};

#pragma pack(pop)//恢復(fù)對齊狀態(tài)

以上結(jié)構(gòu)的大小為16,下面分析其存儲情況,首先為m1分配空間,其偏移量為0,滿足我們自己設(shè)定的對齊方式(4字節(jié)對齊),m1占用1個(gè)字節(jié)。接著開始為 m4分配空間,這時(shí)其偏移量為1,需要補(bǔ)足3個(gè)字節(jié),這樣使偏移量滿足為n=4的倍數(shù)(因?yàn)閟izeof(double)大于n),m4占用8個(gè)字節(jié)。接著為m3分配空間,這時(shí)其偏移量為12,滿足為4的倍數(shù),m3占用4個(gè)字節(jié)。這時(shí)已經(jīng)為所有成員變量分配了空間,共分配了16個(gè)字節(jié),滿足為n的倍數(shù)。如果把上面的#pragma pack(4)改為#pragma pack(16),那么我們可以得到結(jié)構(gòu)的大小為24。(請讀者自己分析)

2、 sizeof用法總結(jié)

在VC中,sizeof有著許多的用法,而且很容易引起一些錯誤。下面根據(jù)sizeof后面的參數(shù)對sizeof的用法做個(gè)總結(jié)。

A.? 參數(shù)為數(shù)據(jù)類型或者為一般變量。例如sizeof(int),sizeof(long)等等。這種情況要注意的是不同系統(tǒng)系統(tǒng)或者不同編譯器得到的結(jié)果可能是不同的。例如int類型在16位系統(tǒng)中占2個(gè)字節(jié),在32位系統(tǒng)中占4個(gè)字節(jié)。

B.? 參數(shù)為數(shù)組或指針。下面舉例說明.

int a[50];? //sizeof(a)=4*50=200; 求數(shù)組所占的空間大小

int *a=new int[50];// sizeof(a)=4; a為一個(gè)指針,sizeof(a)是求指針

?????????????????? //的大小,在32位系統(tǒng)中,當(dāng)然是占4個(gè)字節(jié)。

C.? 參數(shù)為結(jié)構(gòu)或類。Sizeof應(yīng)用在類和結(jié)構(gòu)的處理情況是相同的。但有兩點(diǎn)需要注意,第一、結(jié)構(gòu)或者類中的靜態(tài)成員不對結(jié)構(gòu)或者類的大小產(chǎn)生影響,因?yàn)殪o態(tài)變量的存儲位置與結(jié)構(gòu)或者類的實(shí)例地址無關(guān)。

第二、沒有成員變量的結(jié)構(gòu)或類的大小為1,因?yàn)楸仨毐WC結(jié)構(gòu)或類的每一

個(gè)實(shí)例在內(nèi)存中都有唯一的地址。

下面舉例說明,

Class Test{int a;static double c};//sizeof(Test)=4.

Test *s;//sizeof(s)=4,s為一個(gè)指針。

Class test1{ };//sizeof(test1)=1;

D.? 參數(shù)為其他。下面舉例說明。

?? int func(char s[5]);

?? {

???? cout<<sizeof(s);//這里將輸出4,本來s為一個(gè)數(shù)組,但由于做為函

???????????????????? //數(shù)的參數(shù)在傳遞的時(shí)候系統(tǒng)處理為一個(gè)指針,所

???????????????????? //以sizeof(s)實(shí)際上為求指針的大小。

???? return 1;

}

sizeof(func("1234"))=4//因?yàn)閒unc的返回類型為int,所以相當(dāng)于

???????????????????? //求sizeof(int).


以上為sizeof的基本用法,在實(shí)際的使用中要注意分析VC的分配變量的分配策略,這樣的話可以避免一些錯誤。


--------------------------------------------------------------------------
25.i最后等于多少?
int i = 1;
int j = i++;
if((i>j++) && (i++ == j)) i+=j;

答:
i = 5

--------------------------------------------------------------------------
26.
unsigned short array[]={1,2,3,4,5,6,7};
int i = 3;
*(array + i) = ?

答:
4

--------------------------------------------------------------------------
27.
class A
{
? virtual void func1();
? void func2();
}
Class B: class A
{
? void func1(){cout << "fun1 in class B" << endl;}
? virtual void func2(){cout << "fun2 in class B" << endl;}
}
A, A中的func1和B中的func2都是虛函數(shù).
B, A中的func1和B中的func2都不是虛函數(shù).
C, A中的func2是虛函數(shù).,B中的func1不是虛函數(shù).
D, A中的func2不是虛函數(shù),B中的func1是虛函數(shù).

答:
A

--------------------------------------------------------------------------
28.
數(shù)據(jù)庫:抽出部門,平均工資,要求按部門的字符串順序排序,不能含有"human resource"部門,

employee結(jié)構(gòu)如下:employee_id, employee_name, depart_id,depart_name,wage

答:
select depart_name, avg(wage)
from employee
where depart_name <> 'human resource'
group by depart_name
order by depart_name

--------------------------------------------------------------------------
29.
給定如下SQL數(shù)據(jù)庫:Test(num INT(4)) 請用一條SQL語句返回num的最小值,但不許使用統(tǒng)計(jì)功能,如MIN,MAX等

答:
select top 1 num
from Test
order by num desc

--------------------------------------------------------------------------
30.
輸出下面程序結(jié)果。

#include <iostream.h>

class A
{
public:
?virtual void print(void)
?{
??? cout<<"A::print()"<<endl;
?}
};
class B:public A
{
public:
?virtual void print(void)
?{
?? cout<<"B::print()"<<endl;
?};
};
class C:public B
{
public:
?virtual void print(void)
?{
? cout<<"C::print()"<<endl;
?}
};
void print(A a)
{
?? a.print();
}
void main(void)
{
?? A a, *pa,*pb,*pc;
?? B b;
?? C c;
??
?? pa=&a;
?? pb=&b;
?? pc=&c;
??
?? a.print();
?? b.print();
?? c.print();
??
?? pa->print();
?? pb->print();
?? pc->print();
??
?? print(a);
?? print(b);
?? print(c);
}

A:
A::print()
B::print()
C::print()
A::print()
B::print()
C::print()
A::print()
A::print()
A::print()

--------------------------------------------------------------------------
31.
試編寫函數(shù)判斷計(jì)算機(jī)的字節(jié)存儲順序是開序(little endian)還是降序(bigendian)

答:
bool IsBigendian()
{
?unsigned short usData = 0x1122;
?unsigned char? *pucData = (unsigned char*)&usData;

?return (*pucData == 0x22);
}

--------------------------------------------------------------------------
32.簡述Critical Section和Mutex的不同點(diǎn)

答:
對幾種同步對象的總結(jié)
1.Critical Section
A.速度快
B.不能用于不同進(jìn)程
C.不能進(jìn)行資源統(tǒng)計(jì)(每次只可以有一個(gè)線程對共享資源進(jìn)行存取)

2.Mutex
A.速度慢
B.可用于不同進(jìn)程
C.不能進(jìn)行資源統(tǒng)計(jì)

3.Semaphore
A.速度慢
B.可用于不同進(jìn)程
C.可進(jìn)行資源統(tǒng)計(jì)(可以讓一個(gè)或超過一個(gè)線程對共享資源進(jìn)行存取)

4.Event
A.速度慢
B.可用于不同進(jìn)程
C.可進(jìn)行資源統(tǒng)計(jì)


--------------------------------------------------------------------------
33.一個(gè)數(shù)據(jù)庫中有兩個(gè)表:
一張表為Customer,含字段ID,Name;
一張表為Order,含字段ID,CustomerID(連向Customer中ID的外鍵),Revenue;
寫出求每個(gè)Customer的Revenue總和的SQL語句。

建表
create table customer
(
ID int primary key,Name char(10)
)

go

create table [order]
(
ID int primary key,CustomerID? int foreign key references customer(id) , Revenue float
)

go

--查詢
select Customer.ID, sum( isnull([Order].Revenue,0) )
from customer full join [order]
on( [order].customerid=customer.id )
group by customer.id

--------------------------------------------------------------------------
34.請指出下列程序中的錯誤并且修改
void GetMemory(char *p){
? p=(char *)malloc(100);
}
void Test(void){
? char *str=NULL;
? GetMemory=(str);
? strcpy(str,"hello world");
? printf(str);
}

A:錯誤--參數(shù)的值改變后,不會傳回
GetMemory并不能傳遞動態(tài)內(nèi)存,Test函數(shù)中的 str一直都是 NULL。
strcpy(str, "hello world");將使程序崩潰。

修改如下:
char *GetMemory(){
? char *p=(char *)malloc(100);
? return p;
}
void Test(void){
? char *str=NULL;
? str=GetMemory(){
? strcpy(str,"hello world");
? printf(str);
}

方法二:void GetMemory2(char **p)變?yōu)槎壷羔?
void GetMemory2(char **p, int num)
{
?*p = (char *)malloc(sizeof(char) * num);
}

--------------------------------------------------------------------------
35.程序改錯
class mml
{
? private:
??? static unsigned int x;
? public:
??? mml(){ x++; }
??? mml(static unsigned int &) {x++;}
??? ~mml{x--;}
? pulic:
??? virtual mon() {} = 0;
??? static unsigned int mmc(){return x;}
??? ......?????????????????????
?
};
class nnl:public mml
{
? private:
??? static unsigned int y;
? public:
??? nnl(){ x++; }
??? nnl(static unsigned int &) {x++;}
??? ~nnl{x--;}
? public:
??? virtual mon() {};
???? static unsigned int nnc(){return y;}
??? ......??????????????????
};

代碼片斷:
mml* pp = new nnl;
..........
delete pp;


A:
基類的析構(gòu)函數(shù)應(yīng)該為虛函數(shù)
virtual ~mml{x--;}

--------------------------------------------------------------------------
36.101個(gè)硬幣100真、1假,真假區(qū)別在于重量。請用無砝碼天平稱兩次給出真幣重還是假幣重的結(jié)論。

答:
101個(gè)先取出2堆,
33,33
第一次稱,如果不相等,說明有一堆重或輕
那么把重的那堆拿下來,再放另外35個(gè)中的33
如果相等,說明假的重,如果不相等,新放上去的還是重的話,說明假的輕(不可能新放上去的輕)

第一次稱,如果相等的話,這66個(gè)肯定都是真的,從這66個(gè)中取出35個(gè)來,與剩下的沒稱過的35個(gè)比
下面就不用說了

方法二:
第3題也可以拿A(50),B(50)比一下,一樣的話拿剩下的一個(gè)和真的比一下。
如果不一樣,就拿其中的一堆。比如A(50)再分成兩堆25比一下,一樣的話就在
B(50)中,不一樣就在A(50)中,結(jié)合第一次的結(jié)果就知道了。

--------------------------------------------------------------------------
37.static變量和static 函數(shù)各有什么特點(diǎn)?

答:
static變量:在程序運(yùn)行期內(nèi)一直有效,如果定義在函數(shù)外,則在編譯單元內(nèi)可見,如果在函數(shù)內(nèi),在在定義的block內(nèi)可見;
static函數(shù):在編譯單元內(nèi)可見;

--------------------------------------------------------------------------
38.用C 寫一個(gè)輸入的整數(shù),倒著輸出整數(shù)的函數(shù),要求用遞歸方法 ;

答:
void fun( int a )
{
?printf( "%d", a%10 );
?a /= 10;
?if( a <=0 )return;

?fun( a );
}

--------------------------------------------------------------------------
39.寫出程序結(jié)果:
void Func(char str[100])
{
? printf("%d\n", sizeof(str));
}

答:
4
分析:
指針長度

--------------------------------------------------------------------------
40.int id[sizeof(unsigned long)];
??? 這個(gè)對嗎?為什么??

答:

這個(gè) sizeof是編譯時(shí)運(yùn)算符,編譯時(shí)就確定了
可以看成和機(jī)器有關(guān)的常量。


本文主要包括二個(gè)部分,第一部分重點(diǎn)介紹在VC中,怎么樣采用sizeof來求結(jié)構(gòu)的大小,以及容易出現(xiàn)的問題,并給出解決問題的方法,第二部分總結(jié)出VC中sizeof的主要用法。

1、 sizeof應(yīng)用在結(jié)構(gòu)上的情況

請看下面的結(jié)構(gòu):

struct MyStruct

{

double dda1;

char dda;

int type

};

對結(jié)構(gòu)MyStruct采用sizeof會出現(xiàn)什么結(jié)果呢?sizeof(MyStruct)為多少呢?也許你會這樣求:

sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13

但是當(dāng)在VC中測試上面結(jié)構(gòu)的大小時(shí),你會發(fā)現(xiàn)sizeof(MyStruct)為16。你知道為什么在VC中會得出這樣一個(gè)結(jié)果嗎?

其實(shí),這是VC對變量存儲的一個(gè)特殊處理。為了提高CPU的存儲速度,VC對一些變量的起始地址做了"對齊"處理。在默認(rèn)情況下,VC規(guī)定各成員變量存放的起始地址相對于結(jié)構(gòu)的起始地址的偏移量必須為該變量的類型所占用的字節(jié)數(shù)的倍數(shù)。下面列出常用類型的對齊方式(vc6.0,32位系統(tǒng))。

類型
對齊方式(變量存放的起始地址相對于結(jié)構(gòu)的起始地址的偏移量)

Char
偏移量必須為sizeof(char)即1的倍數(shù)

int
偏移量必須為sizeof(int)即4的倍數(shù)

float
偏移量必須為sizeof(float)即4的倍數(shù)

double
偏移量必須為sizeof(double)即8的倍數(shù)

Short
偏移量必須為sizeof(short)即2的倍數(shù)


各成員變量在存放的時(shí)候根據(jù)在結(jié)構(gòu)中出現(xiàn)的順序依次申請空間,同時(shí)按照上面的對齊方式調(diào)整位置,空缺的字節(jié)VC會自動填充。同時(shí)VC為了確保結(jié)構(gòu)的大小為結(jié)構(gòu)的字節(jié)邊界數(shù)(即該結(jié)構(gòu)中占用最大空間的類型所占用的字節(jié)數(shù))的倍?

posted @ 2006-09-10 20:36 Jerry Cat 閱讀(181) | 評論 (0)編輯 收藏
/********************************************\
|????歡迎轉(zhuǎn)載, 但請保留作者姓名和原文鏈接, 祝您進(jìn)步并共勉!???? |
\********************************************/


讀VC++內(nèi)幕之體悟 - 11
作者: Jerry Cat
時(shí)間: 2006/09/10
鏈接:http://www.shnenglu.com/jerysun0818/archive/2006/09/10/12225.html


通過在函數(shù)OnInitDialog中加入AfxOleLockControl(someActivexControl.GetClsid());可以把ActiveX控件鎖定在內(nèi)存中,這樣,除非程序退出或者調(diào)用了AfxOleUnlockControl,ActiveX控件將總在內(nèi)存中。
posted @ 2006-09-10 20:20 Jerry Cat 閱讀(790) | 評論 (3)編輯 收藏
/********************************************\
|????歡迎轉(zhuǎn)載, 但請保留作者姓名和原文鏈接, 祝您進(jìn)步并共勉!???? |
\********************************************/


動態(tài)鏈接庫小結(jié)
作者: Jerry Cat
時(shí)間: 2006/09/02
鏈接: http://www.shnenglu.com/jerysun0818/archive/2006/09/02/11974.html

一.庫模塊:

?(略)
?

二.實(shí)現(xiàn)(可以使用Visual C++提供的向?qū)韯?chuàng)建動態(tài)鏈接庫和靜態(tài)鏈接庫)

1>:Win32 Static Library

2>:Win32 Dynamic-Link-Library

3>:MFC AppWizard(dll)

Regular Dll With MFC statically linked

Regular Dll using shared MFC Dll

MFC Extension Dll (using shared MFC DLL)
?

三.Win32 DLL可以直接使用API,但是不可以直接使用MFC

MFC AppWizard可以直接使用MFC

. Regular Dll using shared MFC Dll MFC Extension Dll 兩者比較

(表1 )

Regular Dll using shared MFC Dll

MFC Extension Dll (using shared MFC DLL)

1.?????? 能導(dǎo)出 C 風(fēng)格函數(shù),全局變量

2.?????? 能導(dǎo)出資源

1.?????? 能導(dǎo)出 C 風(fēng)格函數(shù),全局變量

2.?????? 能導(dǎo)出資源

3.?????? 能導(dǎo)出 C++ 類,成員函數(shù),重載函數(shù)

允許靜態(tài)或者動態(tài)鏈接 MFC 類庫

只能動態(tài)鏈接 MFC 類庫

它允許客戶程序靜態(tài)或者動態(tài)鏈接

只允許客戶程序動態(tài)鏈接

?

?

?

五.調(diào)用

1> 隱式鏈接

隱式鏈接時(shí),使用 DLL 的程序需要獲取以下信息:

?1. 包含了導(dǎo)出函數(shù)(類)聲明的頭文件

?2. 導(dǎo)入庫 (lib_

?3. 實(shí)際的 DLL

? 使用導(dǎo)出函數(shù)的源文件需要 #include 1 )的頭文件,調(diào)用導(dǎo)出函數(shù)與其它函數(shù)完全一樣

? 建立可執(zhí)行程序時(shí),需要導(dǎo)入 LIB 文件,可通過以下方式實(shí)現(xiàn)

1.?????? Project->Setting->Link Object/Library Modules 編輯框中指定 LIB 名字

2.?????? #pragma comment(lib,”LIB 名字 ”)

例如:我們想使用 opengl 函數(shù),我們可以

1.#include<gl/gl.h>

?#include<gl/glu.h>

2.#pragma comment(lib, “glu32.lib”)

?#pragma comment(lib, “opengl32.lib”)

2> 顯式鏈接

使用 DLL 的程序在運(yùn)行時(shí)通過函數(shù)調(diào)用來顯式加載或卸載 DLL ,并通過函數(shù)調(diào)用來調(diào)用 DLL 的導(dǎo)出函數(shù)。

?1. 使用 LoadLibrary 來加載 DLL ,得到模塊句柄

?2. 調(diào)用 GetProcessAddress 來獲取應(yīng)用程序要調(diào)用的導(dǎo)出函數(shù)指針

?3. 使用結(jié)束后,用 FreeLibrary 來卸載 DLL

? 例如:我們想使用 xxx.dll 中的 GetVersion 函數(shù),我們可以

typedef UINT (CALLBACK* LPFNDLLFUN)(DWORD,UINT);

HINSTANCE hDll = LoadLibrary(“xxx.dll”);

if(hDll != NULL)
{
??? LPFNDLLFUN lpfnDllFun1 = (LPFNDLLFUN)GetProcess(hDll, “GetVersion”);

??? if(lpfnDllFun1)
??? {
??????? // 你的函數(shù)調(diào)用
??? }

?? FreeLibrary(hDll);
}

posted @ 2006-09-02 21:37 Jerry Cat 閱讀(1111) | 評論 (0)編輯 收藏
[轉(zhuǎn)] C++語錄 - 基本教義派

1。如果C函數(shù)的參數(shù)為空,其原形必須含關(guān)鍵字void,而c++可有可無!
2。函數(shù)之所以可以能遞歸,是因?yàn)槊總€(gè)函數(shù)被調(diào)用時(shí),都會把參數(shù)和其他的局部對象復(fù)制到一塊專用的內(nèi)存區(qū)域,而且同一個(gè)函數(shù)的每一個(gè)執(zhí)行進(jìn)程都有一個(gè)單獨(dú)的復(fù)制
3。exter "c"
{??????????????????????????????// 這是個(gè)連接說明
?#include "mychdr.h"? // 告訴c++ 庫 這是個(gè)用C編譯的函數(shù)
}
4。C++采用名字重組技術(shù),給編譯器內(nèi)部的函數(shù)標(biāo)識符重命名,重組的函數(shù)名包含了指定函數(shù)的返回植類型和參數(shù)類型的符號!
5。自動儲存的類型修飾符指定一個(gè)局部變量是自動的,即每次執(zhí)行到定義該變量的語句塊時(shí),都將為該變量在內(nèi)存中產(chǎn)生一個(gè)新的副本,并對其進(jìn)行初始化。
6。靜態(tài)儲存類型初始化值只在語句塊第一次執(zhí)行時(shí)其作用,在隨后的運(yùn)行過程中,變量將保持語句塊上一次執(zhí)行的值!
7。static 儲存類型修飾符使得函數(shù)和變量的標(biāo)識符對于連接到同一個(gè)程序的其他源代碼文件而言是不可見的。
8。寄存器變量的地址是無法取得的,因?yàn)榇蠖鄶?shù)計(jì)算機(jī)的硬件寄存器都不占內(nèi)存地址。
9。C++程序中,默認(rèn)情況下,函數(shù)的所有參數(shù)都是以傳值方式,即把實(shí)參的一個(gè)副本復(fù)制到被調(diào)用函數(shù)的形參中。
10。在編譯器內(nèi)部,用一個(gè)字符數(shù)組來表示字符串常量,對字符串的使用實(shí)際上就是在引用它的內(nèi)部地址,所以把字符串給字符型指針實(shí)際上就是把常量的地址賦給指針!
11。當(dāng)函數(shù)的形參是指向非const 型變量的指針時(shí),不能用const型變量的地址做形參!
12。任何地址都可以賦值給void 型指針,C++允許任何類型的指針自動轉(zhuǎn)換成?void型!
13。typedef 的作用是給一個(gè)已存在的類型起個(gè)別名!
14。指針是儲存地址的變量,地址是相對較小的數(shù)據(jù)單元(在32機(jī)系統(tǒng)中占四個(gè)字節(jié))它儲存另一個(gè)數(shù)據(jù)的地址!
15。# undef 預(yù)處理指令使得以定義的宏在以后的代碼中無效!
16。不帶參數(shù)或所有參數(shù)都有默認(rèn)值的構(gòu)造函數(shù)叫做默認(rèn)構(gòu)造函數(shù),實(shí)例化對象數(shù)組必須有默認(rèn)的構(gòu)造函數(shù);如果類中之少有一個(gè)構(gòu)造函數(shù),編輯器將不在提供默認(rèn)的構(gòu)造函數(shù)!
17。靜態(tài)成員只能在類中申明,必須在類外定義,并且靜態(tài)成員只能存在唯一一個(gè)實(shí)例,即使沒有任何類的實(shí)例,靜態(tài)成員也是已經(jīng)存在的,類的所有實(shí)例都可以使用他,他屬于整個(gè)類!
18。靜態(tài)成員函數(shù)與一般成員函數(shù)的區(qū)別:靜態(tài)成員函數(shù)沒有this指針,因此他無法訪問非靜態(tài)成員!一般的成員函數(shù)隱含this指針
19。初始化和賦值的區(qū)別是:初始化是創(chuàng)建一個(gè)新的對象,然后用已有的的對象去初始化,賦值是兩個(gè)都存在的對象!
20。常量數(shù)據(jù)成員和引用數(shù)據(jù)成員必須使用構(gòu)造函數(shù)的參數(shù)初始化表來初始化,而不能賦值!
21。對象被申明為常量,那么該對象就不可以調(diào)用類中任何非常量型的成員函數(shù)。
22。mutable 修飾符申明的數(shù)據(jù)成員,這樣一個(gè)常量型的成員函數(shù)就可以修改它的值!
23。class member以他們在class?內(nèi)的申明次序來初始化和他們在member initialization list 中出現(xiàn)的次序無關(guān)!
24。string &operation =(const string & rhs);// 意思是將一個(gè)常 string? 指定給另一個(gè)string?
25。string &operator =(const char *rhs);//意思是將一個(gè)常 char * 指定給一個(gè)string?
26。避免傳回內(nèi)部數(shù)據(jù)的handls;
27。public繼承是一種( isa),所以任何事情只要對base class? 而言是真,就一定對其 derived class? 為真。
28。純虛函數(shù)的兩個(gè)接口,他們必須被任何“繼承了他們”的子類重新申明,他們在抽象類中通常沒有定義!
29。純虛函數(shù)的申明主要是為了讓derived class 繼承函數(shù)的接口;
?????????虛函數(shù)的申明主要是為了讓derived class 繼承函數(shù)的接口及其缺省行為
??????? 成員函數(shù)(非虛)的申明主要是為了讓derived class 繼承函數(shù)的實(shí)現(xiàn),表示在 derived? class 中希望不要有不同的行為,即不要重新定義繼承而來的非虛成員函數(shù)!
30。絕對不要重新定義繼承而來的參數(shù)值,因?yàn)樘摂M函數(shù)系動態(tài)綁定,而缺省參數(shù)卻是靜態(tài)綁定的!
31。對象的靜態(tài)型別是程序申明它時(shí)所采用的型別。對象的動態(tài)型別是指對象目前所代表的型別,表現(xiàn)出一個(gè)對象的行為模式!
40:getlin(s,bufsize)表示讀取bufsize-1個(gè)字符給s如果遇到換行符就停下來,添加一個(gè)空字節(jié),丟棄換行符!
41。編輯器將空白字符默認(rèn)為分隔符。
42。不允許重載系統(tǒng)中預(yù)定義的操作,因此重載操作中至少有個(gè)操作數(shù)是用戶自定義類型!
43。全局const申明默認(rèn)情況下是內(nèi)部連接,而在c 中他們是外部連接,如果希望一個(gè)const 對象具有外部連接特性,就必須使用關(guān)鍵字“extern”
44.除了寄存器變量以外,程序中的所有對象都存在內(nèi)存中的。
45。在c++中給void型指針賦值時(shí),不用強(qiáng)制類型轉(zhuǎn)換是一種錯誤!
posted @ 2006-09-02 19:57 Jerry Cat 閱讀(484) | 評論 (0)編輯 收藏
[轉(zhuǎn)]用SIMD指令優(yōu)化程序之拋磚引玉

小談
CPU 緩存體系

  現(xiàn)在的 CPU 依舊采用馮諾伊曼體系,喜歡像傻子一樣從頭執(zhí)行到尾,中途沒有任何的跳轉(zhuǎn)停頓等待。可是現(xiàn)實(shí)情況是,大部分程序里面還是少不了 IF ELSE 之類的判斷,循環(huán)就更加得多了。如何優(yōu)化循環(huán)大家可以自己琢磨,其實(shí)不難,可以參考一下《高質(zhì)量 C\C++ 編程指南》

  現(xiàn)在 CPU 上都有 Level 1 指令緩存(又叫做 L1 Trace )與 Level 1 數(shù)據(jù)緩存( L1 Data Cache )。 PMMX P2 P3 為二者都準(zhǔn)備了 16kb ,我的 P4 Northwood (以下簡稱 P4NW )有 8kbL1 數(shù)據(jù)緩存和 12kb 指令緩存。 CPU 讀取 L1 Data Cache 中的數(shù)據(jù)只需要 1 個(gè)時(shí)鐘周期,速度非常快,應(yīng)該是僅次于寄存器了。數(shù)據(jù)緩存是由 256 或者 512 32bytes 組成的,也就是 32bytes 對齊的,而 P4NW 64bytes 字節(jié)對齊的,并行 4 路,總共 128 行。當(dāng)你處理的數(shù)據(jù)沒有載入緩存的時(shí)候, CPU 將從內(nèi)存讀取緩存行大小的數(shù)據(jù),所以緩存行總是對齊到能被 32 整除的物理地址。 CPU L1 數(shù)據(jù)緩存中的數(shù)據(jù)進(jìn)行操作是最快速的。所以推薦內(nèi)存地址最起碼是 32byte 對齊的。目前編譯器在這個(gè)地方的優(yōu)化已經(jīng)非常好了,一般都是 4byte 對齊,當(dāng)然也都是 32 對齊的。在后面你將會看到, SSE2 要求數(shù)據(jù)是 16 字節(jié)對齊的。

?   緩存類似一個(gè) C++ set 容器,但是不能賦值到一個(gè)任意的內(nèi)存地址。每行本身都有 1 個(gè) 7bit 大小的關(guān)聯(lián)值( set value )要和目標(biāo)內(nèi)存地址的 5 11 位對應(yīng)( 0-4 位已經(jīng)忽略了),也可以理解為,關(guān)聯(lián)值是內(nèi)存段地址的一部分。 PPro 中,有 128 個(gè)關(guān)聯(lián)值對應(yīng)到 2 行,所以最多可以為任意的內(nèi)存單元準(zhǔn)備 2 個(gè)緩存行。 PMMX P2 P3 P4NW 4 個(gè)。由于內(nèi)存是分段的,所以說 CPU 只能為, 5-11 位地址相同的內(nèi)存準(zhǔn)備 2 或者 4 個(gè)不同的緩存行。如何為兩個(gè)內(nèi)存地址賦予相同的關(guān)聯(lián)值呢?把 2 個(gè)地址的低 5bit 去掉,這樣就能被 32 整除了。如果這 2 個(gè)截?cái)嗔说牡刂范际?/span> 4096 1000H )的倍數(shù),那么這兩個(gè)地址就有了相同的關(guān)聯(lián)值。

?   讓我們用匯編加深一下印象,假設(shè) ESI 中是 32 對齊的地址。

? ??????????????????????????????????????? AGAIN:? MOV? EAX,? [ESI]

MOV? EBX,? [ESI+13*4096+4]

MOV ?ECX,? [ESI+20*4096+28]

DEC? ?EDX

JNZ ??AGAIN

   Oh Year ,這里 3 個(gè)地址都有相同的關(guān)聯(lián)值,而且地址跨度都超過了數(shù)據(jù)緩存的大小,可這個(gè)循環(huán)在 PPro 上效率會相當(dāng)?shù)汀.?dāng)你想讀取 ECX 的值的時(shí)候,將沒有空閑的緩存行了 —— 因?yàn)楣蚕硪粋€(gè)關(guān)聯(lián)值,而且 2 行已經(jīng)被使用了。此時(shí) CPU 將騰出最近使用的 2 個(gè)緩存行,一個(gè)已經(jīng)被 EAX 使用。然后 CPU 把這個(gè)緩存行用 [ESI+20*4096] [ESI+20*4096+31] 的內(nèi)存數(shù)據(jù)填充,然后從緩存中讀取 ECX 。聽起來好象相當(dāng)?shù)臒┈崱8釉愀獾氖牵?dāng)又需要讀取 EAX 的時(shí)候,還需要重復(fù)上述的過程,需要對內(nèi)存緩存來回操作,效率相當(dāng)?shù)牡停踔敛蝗绮挥镁彺妗?墒牵绻覀儼训谌懈某桑?/span>

MOV? ECX,? [ESI+20*4096+32]

  哦,不好,看起來,我們的地址超過了 32 ,不能被整除了。可是這樣有了不同的關(guān)聯(lián)值,也就意味著有了 1 個(gè)新行,不再共享可憐的 2 個(gè)行。這樣一來,對三個(gè)寄存器的操作就不需要反復(fù)的用 2 個(gè)緩存行進(jìn)行調(diào)度了,各有一個(gè)了。嘿嘿,這次只需要 3 個(gè)時(shí)鐘周期了,而上一個(gè)要 60 個(gè)周期。這是在 PPro 上的,在后來的 CPU 中都是 4 路的,也就不存在上面的問題了。搞笑的是, Intel 的文檔卻錯誤的說 P2 的緩存是 2 路的。雖然說很少人在用那么古老的 CPU ,可是其中的道理大家應(yīng)該明白。

  可是判斷要訪問的部分?jǐn)?shù)據(jù)是否有相同的關(guān)聯(lián)值,也就是關(guān)于緩存是否能夠命中的問題,是相當(dāng)困難的,匯編還好,用高等級語言編譯過的程序鬼知道是否對緩存做過優(yōu)化呢。所以么,推薦,在程序的核心部分,對性能要求最高的部分,先對齊數(shù)據(jù),然后確保使用的單個(gè)數(shù)據(jù)塊不要超過緩存大小, 2 個(gè)數(shù)據(jù)塊,單個(gè)不要超過緩存大小的一半(仔細(xì)想想為什么,因?yàn)殛P(guān)聯(lián)值的問題,可以緩存分為兩部分處理兩塊)。可是大部分情況下,我們都是使用遠(yuǎn)比數(shù)據(jù)緩存大的多的結(jié)構(gòu),以及編譯器自己返回的指針,然后為了優(yōu)化你可能希望把所有頻繁使用的變量放到一個(gè)連續(xù)的數(shù)據(jù)塊中以充分利用緩存。我們可以這樣做,把靜態(tài)變量數(shù)值拷貝到棧中的局部變量中,等子函數(shù)或者循環(huán)結(jié)束后再拷貝回來。這樣一來就相當(dāng)于把靜態(tài)變量放入了連續(xù)的地址空間中去。

當(dāng)讀取的數(shù)據(jù)不在 L1 Cache 內(nèi)時(shí), CPU 將要從 L2 Cache 讀取 L1 緩存行大小的數(shù)據(jù)到 L1 里去,大概需要 200ns 的時(shí)間(也就是 100Mhz 系統(tǒng)的 20 個(gè)時(shí)鐘周期),但是直到你能夠使用這些數(shù)據(jù)前,又需要有 50-100ns 的延遲。最糟糕的是,如果數(shù)據(jù)也不在 L2 Cache 中,那么就只能從最慢速的內(nèi)存里讀取了,內(nèi)存的龜速哪能和全速的緩存相比。

好了,關(guān)于緩存的知識可以就此打住了,下面開始講如何優(yōu)化緩存。無非就是 3 種方法,硬件預(yù)取( Prefetch )、軟件預(yù)取、使用緩存指令。關(guān)于預(yù)取的注意事項(xiàng)主要有這些:

<!--[if !supportLists]--> 1、? <!--[endif]--> 合理安排內(nèi)存的數(shù)據(jù),使用塊結(jié)構(gòu),提高緩存命中率。

<!--[if !supportLists]--> 2、? <!--[endif]--> 使用編譯器提供的預(yù)取指令。比如ICC中的_mm_prefetch _mm_stream,甚至_mm_load等比較“傳統(tǒng)”的指令。

<!--[if !supportLists]--> 3、? <!--[endif]--> 盡可能少的使用全局的變量或者指針。

<!--[if !supportLists]--> 4、? <!--[endif]--> 程序盡可能少的進(jìn)行判斷跳轉(zhuǎn)循環(huán)。

<!--[if !supportLists]--> 5、? <!--[endif]--> 使用const標(biāo)記,不要在代碼中混合register聲明。

不過要提醒一句,真正提高程序效率的方法不是那種,從頭到尾由于外科手術(shù)般的解剖,一個(gè)一個(gè)地方的優(yōu)化,請抓住程序最核心的部分進(jìn)行優(yōu)化,記住 80-20 規(guī)則。

?

使用 SIMD

先復(fù)習(xí)一下對齊指令, __declspec(aliagn(#)) # 替換為字節(jié)數(shù)。比如想聲明一個(gè) 16 字結(jié)對齊的浮點(diǎn)數(shù)組, __declspec(aliagn(16)) float Array[128] 。需要注意的是,最好充分了解你 CPU 的類型,支持哪些指令集。 SIMD 主要使用在需要同時(shí)操作大量數(shù)據(jù)的工作領(lǐng)域,比如 3D 圖形處理(游戲),物理建模( CAD ),加密,以及科學(xué)計(jì)算領(lǐng)域。據(jù)我所知,目前 GPGPU 也是使用 SIMD 的代表之一。

MMX

主要特性: 57 條指令, 64bit FP 寄存器 MM0-MM7 ,對齊到 8 個(gè) 80bit FP 寄存器 ST0-ST7 。需要數(shù)據(jù) 8 字節(jié)對齊,也就是使用 Packed 數(shù)字。

PS :這里冒出了一個(gè)問題,為什么 Intel 要把 MMX 的寄存器和 FPU 的寄存器混合起來使用呢?因?yàn)檫@里牽涉到一個(gè) FPU 狀態(tài)切換問題,后面會提到,當(dāng)你在一段代碼中又要用到 MMX 指令又要用到傳統(tǒng)的 FPU 指令,那么需要保存 FPU 狀態(tài),或者退出 MMX 。可是這種操作對于 FPU 來說非常昂貴,而且對于多任務(wù)操作系統(tǒng)來說,近乎于不可能完成的任務(wù) —— 同時(shí)有許多程序,有些需要 MMX ,有些不需要,而正確地進(jìn)行調(diào)度會變得非常困難。所以 Intel 將保存狀態(tài)的工作完全交給了 CPU 自己,軟件人員無須作太多這方面的工作,這樣一來,就向前向后兼容了多任務(wù)操作系統(tǒng),比如 Windows Linux 。后來隨著操作系統(tǒng)和 CPU 的不斷升級,操作系統(tǒng)開發(fā)人員發(fā)布了一個(gè)補(bǔ)丁包,就可以讓操作系統(tǒng)使用新的寄存器。這時(shí)人們都發(fā)現(xiàn) Intel 的這種做法是相當(dāng)短視的,這可以當(dāng)作一個(gè)重大的失誤。后來 Intel 通過引入了新的浮點(diǎn)指令集,這時(shí)才加入 XMM 寄存器。可造成這段故事的原因卻根本不是技術(shù)問題,保證兼容性也是一個(gè)方面,總之真的說不清楚。你只要記得無法同時(shí)使用 MMX FPU 就可以了, CPU 要進(jìn)行模式切換。

SSE1

主要特性: 128bit FP 寄存器 XMM0-XMM7 。增加了數(shù)據(jù)預(yù)取指令。額外的 64bit 整數(shù)支持。支持同時(shí)處理 4 個(gè)單精度浮點(diǎn)數(shù),也就是 C\C++ 里的 float

適用范圍:多媒體信號處理

SSE2

主要特性: 128bit FP 寄存器支持處理同時(shí)處理 2 個(gè)雙精度 double 浮點(diǎn)數(shù),以及 16byte 8word 4dword 2quadword 整數(shù)。

適用范圍: 3D 處理 語音識別 視頻編碼解碼

SSE3

主要特性:增加支持非對稱 asymmetric 和水平 horizontal 計(jì)算的 SIMD 指令。為 SIMD 提供了一條特殊的寄存器 load 指令。線程同步指令。

適用范圍:科學(xué)計(jì)算 多線程程序

手頭工具

1 、選擇一個(gè)合適的編譯器,推薦用 Intel C++ Compiler (以下簡稱 ICC ),以及 Visual Studio .NET 2003 及以上 IDE 附帶的 C++ 編譯器。同時(shí), Microsoft C++ Compiler 也支持 AMD 3DNow GCC C++ Compiler 沒有測試。

2 Intel 以及 AMD 的匯編指令集手冊。這個(gè)是必需的,強(qiáng)烈建議每個(gè)C++ Coder人手準(zhǔn)備一份。

? 所有的都用 C++ 混合變成的方式實(shí)現(xiàn)

使用范例:

向量乘法在 3D 處理中非常非常多,多半用于計(jì)算單位矢量的夾角。

我們先定義一個(gè)頂點(diǎn)結(jié)構(gòu)。

__declspec(align( 16 ))? struct ?Vertex{
????
float
?x,y,z,w;
};
??? 16字節(jié)對齊的結(jié)構(gòu),其實(shí)本身也是16字節(jié)的東西。如果沒有對齊,運(yùn)行時(shí)會報(bào)錯。

w是其次坐標(biāo)系的參數(shù),處理向量的時(shí)候不需要用到。我的函數(shù)是這樣的:

float ?Dot(Vertex * ?v1,Vertex * ?v2)
{
????Vertex?tmp;
????__asm{
????????MOV?EAX,[v1];
????????MOVAPS?XMM0,[EAX];
????????MOV?EAX,[v2];
????????MOVAPS?XMM1,[EAX];
????????MULPS?XMM0,XMM1;
????????MOVAPS?tmp,XMM0;
????};
????
return ?tmp.x? + ?tmp.y? +
?tmp.z;
};

??? VC中反匯編之:
?1?float?Dot(Vertex*?v1,Vertex* ?v2)
?2?
{
?3?
0041C690??push????????ebx??
?4?
0041C691??mov?????????ebx,esp?
?5?0041C693??sub?????????esp,8
?
?6?
0041C696??and?????????esp,0FFFFFFF0h?
?7?0041C699??add?????????esp,4
?
?8?
0041C69C??push????????ebp??
?9?0041C69D??mov?????????ebp,dword?ptr?[ebx+4
]?
10?0041C6A0??mov?????????dword?ptr?[esp+4
],ebp?
11?
0041C6A4??mov?????????ebp,esp?
12?
0041C6A6??sub?????????esp,0E8h?
13?
0041C6AC??push????????esi??
14?
0041C6AD??push????????edi??
15?0041C6AE??lea?????????edi,[ebp-
0E8h]?
16?
0041C6B4??mov?????????ecx,3Ah?
17?
0041C6B9??mov?????????eax,0CCCCCCCCh?
18?
0041C6BE??rep?stos????dword?ptr?[edi]?
19?
????Vertex?tmp;
20?
????__asm{
21?
????????MOV?EAX,[v1];
22?
0041C6C0??mov?????????eax,dword?ptr?[v1]?
23?
????????MOVAPS?XMM0,[EAX];
24?
0041C6C3??movaps??????xmm0,xmmword?ptr?[eax]?
25?
????????MOV?EAX,[v2];
26?
0041C6C6??mov?????????eax,dword?ptr?[v2]?
27?
????????MOVAPS?XMM1,[EAX];
28?
0041C6C9??movaps??????xmm1,xmmword?ptr?[eax]?
29?
????????MULPS?XMM0,XMM1;
30?
0041C6CC??mulps???????xmm0,xmm1?
31?
????????MOVAPS?tmp,XMM0;
32?
0041C6CF??movaps??????xmmword?ptr?[tmp],xmm0?
33?
????};
34?????return?tmp.x?+?tmp.y?+
?tmp.z;
35?
0041C6D3??fld?????????dword?ptr?[tmp]?
36?0041C6D6??fadd????????dword?ptr?[ebp-
1Ch]?
37?0041C6D9??fadd????????dword?ptr?[ebp-
18h]?
38?};
??? 前面都是保護(hù)現(xiàn)場入Stack的代碼,沒有必要管。我之所以這樣,在Stack中聲明了一個(gè)零時(shí)變量返回之,是為了減少代碼的行數(shù)。有興趣地可以參考本文后面引用資料中的Intel范例,代碼多的多,功能卻一樣。這樣就可以利用SIMD計(jì)算點(diǎn)乘了。圖示:
??? 這種頂點(diǎn)格式稱為AoS(Array of structure),這種結(jié)構(gòu)的好處是,能夠和現(xiàn)有的程序結(jié)構(gòu),比如D3D中的FVF頂點(diǎn)格式,和GL中的頂點(diǎn)格式。但是,由于許多情況下,并沒有使用第四各浮點(diǎn)數(shù),這就讓SIMD指令浪費(fèi)了25%的性能。于是有了SoA格式,讓我們重新來過。
??? 我借用了一下上面一個(gè)結(jié)構(gòu)的指令,還是沒有用_mm_128格式,讓大家看得清楚一些:
__declspec(align( 16 ))? struct ?Vertex_soa{
?????
float ?x[ 4 ],y[ 4 ],z[ 4 ],w[ 4
];
};
??? 依舊16字節(jié)對齊。計(jì)算函數(shù)如下:
?1?void?Dot(Vertex_soa*?v1,Vertex*?v2,float* ?result)
?2?
{
?3?
????Vertex?tmp1,tmp2;
?4?
????__asm{
?5?
????????MOV?ECX,v1;
?6?
????????MOV?EDX,v2;
?7?

?8? ????????MOVAPS?XMM7,[ECX];
?9?????????MOVAPS?XMM6,[ECX+16
];
10?????????MOVAPS?XMM5,[ECX+32
];
11?????????MOVAPS?XMM4,[ECX+48
];
12?
????????MOVAPS?XMM0,XMM7;
13?
????????UNPCKLPS?XMM7,XMM6;
14?
????????MOVLPS?[EDX],XMM7;
15?????????MOVHPS?[EDX+16
],XMM7;
16?
????????UNPCKHPS?XMM0,XMM6;
17?????????MOVLPS?[EDX+32
],XMM0;
18?????????MOVHPS?[EDX+48
],XMM0;
19?

20? ????????MOVAPS?XMM0,XMM5;
21?
????????UNPCKLPS?XMM5,XMM4;
22?
????????UNPCKHPS?XMM0,XMM4;
23?????????MOVLPS?[EDX+8
],XMM5;
24?????????MOVHPS?[EDX+24
],XMM5;
25?????????MOVLPS?[EDX+40
],XMM0;
26?????????MOVHPS?[EDX+56
],XMM0;
27?

28? ????????MOVAPS?XMM3,[EDX];
29?????????MOVAPS?XMM2,[EDX+16
];
30?????????MOVAPS?XMM1,[EDX+32
];
31?????????MOVAPS?XMM0,[EDX+48
];
32?

33? ????????MULPS?XMM3,XMM2;
34?
????????MULPS?XMM1,XMM0;
35?
????????MOVAPS?tmp2,XMM1;
36?
????????MOVAPS?tmp1,XMM3;
37?
????};
38?????result[0]?=?tmp1.x?+?tmp1.y?+
?tmp1.z;
39?????result[1]?=?tmp2.x?+?tmp2.y?+
?tmp2.z;
40?};
??? Oh Year,就是這樣了,同時(shí)計(jì)算了1對乘法。我在代碼中借用了一下前面的頂點(diǎn)結(jié)構(gòu),這樣方便一些。至于SOA格式,請看前面的聲明。很多代碼都是轉(zhuǎn)換Stack中的內(nèi)存格式,轉(zhuǎn)換成AOS格式,這樣才能使用SIMD指令計(jì)算。

??? 通過上面的演示,想必大家已經(jīng)對SIMD有了個(gè)直觀地認(rèn)識,其實(shí)在自己的代碼中加入這些是非常方便與容易的。雖然說現(xiàn)在的CPU性能已經(jīng)提高了許多,性能也強(qiáng)了許多,可是在諸多對性能要求高的地方,還是非常烤煙程序員的水平的。
posted @ 2006-08-24 21:00 Jerry Cat 閱讀(653) | 評論 (0)編輯 收藏
     摘要: 用文檔序列化來保存打開文件[理論聯(lián)系實(shí)際] 文檔與序列化 ...  閱讀全文
posted @ 2006-08-17 00:38 Jerry Cat 閱讀(895) | 評論 (1)編輯 收藏
/********************************************\
|????歡迎轉(zhuǎn)載, 但請保留作者姓名和原文鏈接, 祝您進(jìn)步并共勉!???? |
\********************************************/


讀VC++內(nèi)幕之體悟 - 10

作者: Jerry Cat
時(shí)間: 2006/08/05
鏈接:
http://www.shnenglu.com/jerysun0818/archive/2006/08/05/10866.html

10.?dāng)U展DLL支持C++接口,并要求客戶程序被動態(tài)連接到相同版本的MFC庫,該庫RELEASE版本對應(yīng)文件為mfc42.dll。正規(guī)DLL可以導(dǎo)出C風(fēng)格的函數(shù),卻不能導(dǎo)出C++類。
posted @ 2006-08-05 17:56 Jerry Cat 閱讀(655) | 評論 (0)編輯 收藏
僅列出標(biāo)題
共14頁: 1 2 3 4 5 6 7 8 9 Last 

<2025年12月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用鏈接

留言簿(7)

隨筆檔案

最新隨筆

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              亚洲国产精品激情在线观看| 久久成人一区| 久久久亚洲高清| 亚洲高清在线观看| 亚洲最新色图| 久久久蜜桃一区二区人| 欧美精品日韩www.p站| 欧美一区二区免费观在线| 久久综合九色欧美综合狠狠| 欧美午夜激情在线| 在线日韩电影| 亚洲欧美日韩综合国产aⅴ | 亚洲一区在线观看免费观看电影高清| 久久精品久久99精品久久| 欧美乱妇高清无乱码| 国产一区99| 在线观看国产精品淫| 亚洲视频中文| 欧美风情在线| 午夜日本精品| 欧美三级韩国三级日本三斤| 尤物99国产成人精品视频| 亚洲一品av免费观看| 麻豆久久婷婷| 亚洲欧美日韩综合| 欧美日韩大片| 亚洲黄色有码视频| 久久久久久久久伊人| 一本大道av伊人久久综合| 麻豆精品精华液| 国产午夜精品在线| 亚洲在线成人精品| 亚洲欧洲日本专区| 久久久精品国产免费观看同学| 国产精品久久久99| 中国成人黄色视屏| 亚洲国产精品久久久久婷婷884| 性欧美18~19sex高清播放| 国产精品h在线观看| 亚洲毛片在线看| 欧美国产日韩一区二区| 久久久久成人精品| 国产人成一区二区三区影院| 亚洲在线视频网站| 亚洲剧情一区二区| 欧美理论电影在线观看| 亚洲片在线观看| 欧美电影在线观看完整版| 欧美影院成人| 国产一区美女| 久久国产66| 性高湖久久久久久久久| 国产精品天美传媒入口| 亚洲欧美一区二区视频| 亚洲人成亚洲人成在线观看图片| 美女视频网站黄色亚洲| 亚洲国产欧美日韩另类综合| 免费的成人av| 久久视频在线视频| 在线色欧美三级视频| 免费在线成人av| 久热精品视频在线| 91久久国产综合久久| 欧美激情一区二区在线| 久久这里有精品15一区二区三区| 影音先锋另类| 欧美成黄导航| 美腿丝袜亚洲色图| 亚洲美女在线一区| 亚洲精品一区二区在线观看| 欧美日韩免费精品| 亚洲一区二区三区在线| 亚洲性av在线| 国产一区二区三区免费在线观看| 久久精品在线| 久久久久久久一区| 91久久精品国产91性色| 91久久精品国产| 欧美日韩一二三区| 先锋a资源在线看亚洲| 午夜精品一区二区三区在线播放| 国产日韩在线一区| 麻豆精品精华液| 欧美护士18xxxxhd| 亚洲尤物影院| 性感少妇一区| 在线日韩av片| 日韩视频专区| 国产日韩欧美日韩大片| 免费观看成人| 欧美精品在线免费播放| 午夜激情综合网| 久久激情五月婷婷| 日韩亚洲欧美精品| 亚洲欧美国产高清| 在线精品亚洲| av成人免费| 国产综合色产在线精品| 欧美激情一区二区三区在线视频观看 | 欧美日韩免费观看一区二区三区| 亚洲影视在线播放| 欧美中文在线观看| 亚洲美女av网站| 亚洲欧美日韩综合| 亚洲国产精品成人精品| 夜夜嗨av一区二区三区中文字幕| 国产午夜精品理论片a级大结局| 欧美不卡在线| 国产精品久久久久久久午夜片| 久久九九久精品国产免费直播| 免费欧美日韩| 翔田千里一区二区| 麻豆成人综合网| 午夜精品久久久久久久蜜桃app| 久久久99爱| 亚洲一区二区三区免费视频 | 久久在线免费视频| 亚洲尤物视频在线| 久久综合九色综合欧美就去吻| 亚洲午夜一二三区视频| 久久久综合激的五月天| 亚洲午夜久久久| 鲁大师成人一区二区三区 | 久久精品色图| 欧美日韩国产黄| 老牛嫩草一区二区三区日本| 欧美日韩精品一区二区在线播放| 久久嫩草精品久久久精品| 欧美日韩国产一区二区三区| 另类激情亚洲| 国产精品久久久久av免费| 欧美激情视频一区二区三区不卡| 国产欧美日韩麻豆91| 亚洲精品久久久久中文字幕欢迎你 | 亚洲视频精选| 美国成人直播| 久久久久国色av免费看影院| 欧美午夜在线观看| 亚洲电影免费观看高清完整版在线 | 午夜亚洲福利在线老司机| 欧美国产91| 免费视频亚洲| 国产亚洲欧洲997久久综合| 99re国产精品| 亚洲老司机av| 狂野欧美一区| 久久综合久久久| 国产乱肥老妇国产一区二| 99精品欧美一区| 亚洲美女一区| 欧美成va人片在线观看| 久久免费国产精品| 国产欧美一区二区白浆黑人| 中文在线不卡视频| 在线亚洲激情| 欧美日本国产在线| 亚洲国产精品成人精品| **性色生活片久久毛片| 久久国产主播| 久久久国产精彩视频美女艺术照福利 | 亚洲看片免费| 欧美成人精品在线视频| 免费中文日韩| 在线免费观看视频一区| 久久久噜噜噜久久中文字免| 久久精品人人做人人爽| 国产日产欧产精品推荐色| 亚洲天堂av图片| 亚洲一区二区三区777| 欧美日韩精品欧美日韩精品一| 亚洲激情在线观看| 亚洲美女在线视频| 欧美极品在线播放| 亚洲精品一级| 在线视频欧美日韩精品| 欧美日韩大片| 一区二区三区国产盗摄| 亚洲综合欧美日韩| 国产精品欧美久久| 亚洲午夜精品一区二区| 午夜精品久久久久久久99热浪潮| 国产精品成人v| 亚洲欧美日韩在线综合| 欧美在线播放高清精品| 国产一区二区| 久久久亚洲午夜电影| 欧美激情视频一区二区三区不卡| 亚洲人成在线影院| 欧美日韩第一页| 亚洲无线一线二线三线区别av| 先锋影音网一区二区| 国产在线观看91精品一区| 久久夜色精品国产噜噜av| 亚洲第一精品影视| 999亚洲国产精| 国产精品福利在线观看网址| 亚洲欧美国产高清va在线播| 久久躁狠狠躁夜夜爽| 亚洲国产欧美一区二区三区丁香婷| 欧美多人爱爱视频网站|