GuiToolkit(開(kāi)源,類似Visual Studio 2003風(fēng)格)
http://www.beyondata.com/default.htm
GardenUI(免費(fèi),界面效果挺好的,XML,代碼 界面 分離)
http://www.gardenui.com/
CJLib(開(kāi)源,免費(fèi),UNICODE編碼,是xtreme toolkit的前生,但xtreme toolkit收費(fèi)了)
http://www.codejock.com/
LibUIDK(部分免費(fèi),不開(kāi)源,效果好,適合貼圖)
http://www.iuishop.com/download.htm
BCGControlBar(收費(fèi),界面感覺(jué)和Office類似)
http://www.bcgsoft.com
SKin++(收費(fèi),界面很好看,從它的截圖上可以看出)
http://www.uipower.com/
SkinMagic(收費(fèi),看起來(lái)像Office)
http://appspeed.com/html/download.html
ActiveSkin(未知)
http://www.softshape.com/software/develop/
SYGUI(收費(fèi),類似Office)
http://www.sygui.com/
?
???? 一個(gè)View中用到了一個(gè)CListCtrl,在OnInitialUpdate函數(shù)里面他調(diào)用了m_listCtrl.ModifyStyleEx(0, LVS_EX_FULLROWSELECT);但是結(jié)果是并沒(méi)有改變View中這個(gè)ListCtrl的效果。
?
???? 仔細(xì)的查閱了MSDN的關(guān)于ModifyStyleEx的說(shuō)明,發(fā)現(xiàn)沒(méi)什么可以的地方,調(diào)試幾遍發(fā)現(xiàn)也沒(méi)異常,最后在網(wǎng)上一搜索ModifyStyleEx,結(jié)果發(fā)現(xiàn)碰到這個(gè)問(wèn)題的朋友還真不少,有一遍關(guān)于ModifyStyle和ModifyStyleEx無(wú)法改變樣式的解決方法的文章被轉(zhuǎn)載得到處都是,不僅感慨現(xiàn)在的互聯(lián)網(wǎng)信息重復(fù)程度~~結(jié)果看完文章很失望,他完全是重新Create了一個(gè)控件。
?
???? 最后經(jīng)過(guò)努力,發(fā)現(xiàn)使用SetExtendStyle函數(shù)就可以實(shí)現(xiàn)改變Style的功能。
?
???? 有一點(diǎn)是可以肯定地,如果你重構(gòu)一個(gè)控件繼承自CListCtrl,那么你可以在該控件的OnCreate中使用ModifyStyle或者M(jìn)odifyStyleEx,這都是可以達(dá)到目的的,但是如果控件的一個(gè)實(shí)例是另一個(gè)窗口的成員變量,那么你在這個(gè)窗口的初始化函數(shù)中調(diào)用該控件的ModifyStyle或者M(jìn)odifyStyleEx是不能達(dá)到目的的,有些關(guān)聯(lián)的一個(gè)說(shuō)明是SetWindowLong會(huì)因?yàn)榭丶驼{(diào)用者不在同一進(jìn)程而失敗(ModifyStyle和ModifyStyleEx函數(shù)中有調(diào)用SetWindowLong).
數(shù)據(jù)庫(kù)安裝后的root的用戶只是對(duì)本機(jī)具有全部的權(quán)限,但是不具備客戶機(jī)的連接
當(dāng)無(wú)法遠(yuǎn)程連接的時(shí)候,建議新建一個(gè)用戶,并確具有全部權(quán)限,問(wèn)題一般可以得到解決.
動(dòng)態(tài)鏈接庫(kù)的連接方式: 顯式鏈接,隱式鏈接
在命令行下運(yùn)行當(dāng)前目錄下(如C:\Documents and Settings\Tony\桌面\dll1\Debug),運(yùn)行命令dumpbin,如果不能運(yùn)行,說(shuō)明環(huán)境找到損壞,利用vcvars32.bat(VC87 / VC7 目錄下Bin 文件夾直接拖入然后運(yùn)行). 運(yùn)行dumpbin -exports dll1.dll可以看到DLL中到處函數(shù)名.
Code:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
dll1.cpp:
_declspec(dllexport) int add(int a, int b )
{
???????return a+b;
}
_declspec(dllexport)int subtract(int a, int b)
{
???????return a-b;
}
_declspec(dllexport)表示為導(dǎo)出函數(shù),可供應(yīng)用程序調(diào)用。"extern C"表示,可以使用其他編程語(yǔ)言訪問(wèn)dll中的函數(shù).
編譯后可以得到DLL1.DLL文件.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
dlltest.dlg
extern int add(int x,int y);
extern int subtract(int x,int y);
//_declspec(dllimport) int add(int a, int b )
//_declspec(dllimport)int subtract(int a, int b)?? //這樣的方法告訴編譯器這些函數(shù)是從一個(gè)dll中調(diào)用的函數(shù).編譯器就能調(diào)用相應(yīng)的lib文件,提高運(yùn)行效率
extern可以置于變量或者函數(shù)前,以標(biāo)示變量或者函數(shù)的定義在別的文件中,提示編譯器遇到此變量和函數(shù)時(shí)在其他模塊中尋找其定義
?CString str;
?str.Format("3+5=%d",add(3,5));
?MessageBox(str);
編譯器工程屬性LINK-->input-->additional dependencies 添加相應(yīng)的lib文件,LINK-->input-->Module defintion file添加def文件.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
如何顯式的加載一個(gè)動(dòng)態(tài)鏈接庫(kù)
動(dòng)態(tài)加載不需要lib文件,只需要dll文件即可
HINSTANCE與HMODULE可以通用
HInstance hinst;
hinst = Loadlibrary("dll2.dll");???????? //顯式加載
typedef int (*ADDPROC)(int a , int b);??????????? //定義一個(gè)函數(shù)指針
ADDPROC Add = (ADDPROC)getprocAdress(hinst, "add");??? //獲得函數(shù)指針
if(!add)
{
???messagebox("fail");
}
else
{
????CString str;
????str.Format("3+5=%d",add(3,5));
????MessageBox(str);
}
在mysql下經(jīng)常會(huì)遇到漢字的顯示問(wèn)題,解決方案如下:
1: 設(shè)定全部的數(shù)據(jù)庫(kù)格式為utf-8,包括字段的字符集格式.
2: 正常讀寫即可.
3: 注意mysql-front對(duì)于字符集的支持有些問(wèn)題,很多時(shí)候可以正常寫入讀出,但是在mysql-front
卻顯示亂碼.命令行格式下顯示正常.
connect string: Driver={mySQL ODBC 3.51 Driver};Server=localhost;"
??????????????????????????"Port=3306;Option=4;Database=mysql;Uid=root;Pwd=;
main()
{
? ?? ???int a,b;
? ?? ???int i;
? ?? ???a=b=1;
? ?? ???for(i=1;i<100;i++)
? ?? ???{
? ?? ?? ?? ?? ? printf("%4d%4d",a,b);
? ?? ?? ?? ?? ? a+=b;
? ?? ?? ?? ?? ? b+=a;
? ?? ???}
? ?? ???printf("\n");
}
步驟如下:
1:在安裝好mysql 5.0
2:?? 安裝GUI管理工具,我用的的是mysql -front
3:???安裝好驅(qū)動(dòng),這里我使用的是mysql-connector-odbc-3.51.12-win32,這個(gè)可以在mysql官網(wǎng)下載到
4:連接字符串:"Driver={mySQL ODBC 3.51 Driver};Server=localhost;"
??"Port=3306;Option=4;Database=storage;Uid=sa;Pwd=;"
?????????IP地址為:localhost?;端口為:3306;選項(xiàng)默認(rèn)為:4 ; 數(shù)據(jù)庫(kù)名:storage; 用戶名:sa; 密碼為空
另外在.net平臺(tái)下連接mysql 可以參照下面這篇文章:
http://www.microsoft.com/china/community/Columns/Luyan/6.mspx總體感覺(jué)mysql 是中小企業(yè)設(shè)計(jì)數(shù)據(jù)管理必須的系統(tǒng), 希望大家都能做好.
Demonstrates ? how ? to ? use ? plain ? C ? to ? create ? a ? MySQL ? database, ? connect ? to ? it, ? create ? a ? table ? with ? fields, ? populate ? the ? table, ? execute ? an ? SQL ? query, ? and ? print ? the ? results. ? No ? MFC ? required ? - ? uses ? only ? plain ? C. ?
? ?
? #include ? <conio.h> ?
? #include ? <stdarg.h> ?
? #include ? <stdio.h> ?
? #include ? <stdlib.h> ?
? #include ? "winsock.h" ?
? #include ? "mysql.h" ?
? ?
? MYSQL ? ? ? ? ? *mysql ? = ? NULL; ?
? ?
? void ? MySQLError(void) ?
? { ?
? fprintf(stderr, ? "%s\n", ? mysql_error(mysql)); ?
? exit(1); ?
? } ?
? ?
? void ? ExecuteSQL(char ? *fmt, ? ...) ?
? { ?
? char ? SQL[1000] ? = ? {0}; ?
? int ? ? retval; ?
? va_list ? args; ?
? va_start(args, ? fmt); ?
? if ? (_vsnprintf(SQL, ? sizeof(SQL)-1, ? fmt, ? args) ? < ? 0) ?
? { ?
? fprintf(stderr, ? "SQL ? query ? truncated! ? Increase ? SQL ? buffer ? size ? in ? ExecuteSQL\n"); ?
? exit(1); ?
? } ?
? va_end(args); ?
? retval ? = ? mysql_query(mysql, ? SQL); ?
? if ? (retval) ?
? { ?
? fprintf(stderr, ? "Original ? SQL ? Statement: ? %s\n", ? SQL); ?
? fprintf(stderr, ? "%s\n", ? mysql_error(mysql)); ?
? exit(2); ?
? } ?
? } ?
? ?
? int ? main() ?
? { ?
? UINT ? ? ? ? ? ? ? ? ? i; ?
? UINT ? ? ? ? ? ? ? ? ? FieldCount; ?
? MYSQL_RES ? ? ? *res ? ? ? ? ? ? ? ? ? = ? NULL; ?
? MYSQL_ROW ? ? ? ? row ? ? ? ? ? ? ? ? ? = ? NULL; ?
? MYSQL_FIELD ? *field; ?
? ?
? char ? ? ? ? ? ? *DBName ? ? ? ? ? ? = ? "Test"; ?
? char ? ? ? ? ? ? *TableName ? ? ? = ? "People"; ?
? char ? ? ? ? ? ? *CreateDB ? ? ? ? = ? "CREATE ? DATABASE ? IF ? NOT ? EXISTS ? %s"; ?
? char ? ? ? ? ? ? *DropTable ? ? ? = ? "DROP ? TABLE ? IF ? EXISTS ? %s"; ?
? char ? ? ? ? ? ? *CreateTable ? = ? "CREATE ? TABLE ? IF ? NOT ? EXISTS ? %s ? (\n" ?
? ? "ID ? ? ? ? ? ? ? ? ? INT ? UNSIGNED ? AUTO_INCREMENT, ? \n" ?
? ? "FirstName ? ? VARCHAR(32), ? \n" ?
? ? "MiddleName ? VARCHAR(32), ? \n" ?
? ? "LastName ? ? ? VARCHAR(32), ? \n" ?
? ? "Address1 ? ? ? VARCHAR(50), ? \n" ?
? ? "Address2 ? ? ? VARCHAR(50), ? \n" ?
? ? "City ? ? ? ? ? ? ? VARCHAR(50), ? \n" ?
? ? "State ? ? ? ? ? ? VARCHAR(2), ? \n" ?
? ? "Zip ? ? ? ? ? ? ? ? VARCHAR(5), ? \n" ?
? ? "Email ? ? ? ? ? ? VARCHAR(50), ? \n" ?
? ? "Gender ? ? ? ? ? VARCHAR(1), ? \n" ?
? ? "WorkPhone ? ? VARCHAR(50), ? \n" ?
? ? "HomePhone ? ? VARCHAR(50), ? \n" ?
? ? "CellPhone ? ? VARCHAR(50), ? \n" ?
? ? "BirthDate ? ? DATE ? NULL, ? \n" ?
? ? "Primary ? Key ? (ID) ? \n" ?
? ? ")\n"; ?
? char ? ? ? ? ? ? *AddRecord ? ? ? = ? "INSERT ? INTO ? %s ? (FirstName, ? LastName) ? VALUES ? ('FirstName ? %03d', ? 'LastName ? %03d')"; ?
? char ? ? ? ? ? ? *GetRecords ? ? = ? "SELECT ? ID, ? FirstName, ? LastName ? FROM ? %s"; ?
? ?
? ?
? ?
? // ? Initialize ? MySQL ?
? mysql ? = ? mysql_init(NULL); ?
? ?
? // ? Connect ? to ? MySQL ?
? if ? (!(mysql_real_connect(mysql, ? "localhost", ? "admin", ? "", ? NULL, ? mysql->port, ? 0, ? 0))) ? ?
? MySQLError(); ?
? ?
? // ? Create ? database ?
? ExecuteSQL(CreateDB, ? DBName); ?
? ?
? // ? Connect ? to ? temporary ? database ?
? if ? (mysql_select_db(mysql, ? DBName)) ?
? MySQLError(); ?
? ?
? // ? Delete ? table ? if ? it ? already ? exists. ?
? ExecuteSQL(DropTable, ? TableName); ?
? ?
? // ? Create ? table ?
? ExecuteSQL(CreateTable, ? TableName); ?
? ?
? // ? Insert ? some ? data ? into ? the ? table. ?
? for ? (i ? = ? 0; ? i ? < ? 200; ? i++) ?
? ExecuteSQL(AddRecord, ? TableName, ? i, ? i); ?
? ?
? // ? Execute ? query ?
? ExecuteSQL(GetRecords, ? TableName); ?
? ?
? // ? Store ? the ? recordset ?
? if ? ((res ? = ? mysql_store_result(mysql)) ? == ? NULL) ?
? MySQLError(); ?
? ?
? // ? Print ? the ? recordset ?
? printf("Table ? %s\n", ? TableName); ?
? while((field ? = ? mysql_fetch_field(res)) ? != ? NULL) ?
? printf("%s\t", ? field->name); ?
? printf("\n"); ?
? FieldCount ? = ? mysql_num_fields(res); ?
? while((row ? = ? mysql_fetch_row(res)) ? != ? NULL) ? ?
? { ?
? for ? (i ? = ? 0; ? i ? < ? FieldCount; ? i++) ? ?
? printf("%s\t", ? row[i]); ?
? printf("\n"); ?
? } ?
? printf("\nTotal ? rows: ? %d\n", ? mysql_num_rows(res)); ?
? ?
? // ? Free ? the ? recordset ?
? mysql_free_result(res); ?
? ?
? // ? Close ? the ? connection ?
? mysql_close(mysql); ?
? ?
? printf("\nPrint ? any ? key ? to ? continue...\n"); ?
? getche(); ?
? } ?
? ?
? 如果有問(wèn)題,請(qǐng)加入mysql++.lib????
在VC里的toos->option->directories中將include增加一個(gè)c:\mysql\include,將lib增加一個(gè)c:\mysql\lib,將libmysql.dll和libmysql.lib拷到當(dāng)前目錄下,并且把libmysql.lib增加到工程中。
2,????? 建立與服務(wù)器的連接。
Include <mysql.h> //包含頭文件
MYSQL *conn;//定義一個(gè)MYSQL類型結(jié)構(gòu),這個(gè)幾乎在所有的后面的編程中都需要
MYSQL *mysql_init(MYSQL *conn);//如果conn=NULL,返回一個(gè)新分配的句柄結(jié)構(gòu)返回,反之則重新初始化該結(jié)構(gòu),出現(xiàn)錯(cuò)誤則返回NULL;
MYSQL *mysql_real_connect(MYSQL * connection,const char *server_host,const char *sql_urs_name,const char *sql_password,const char *db_name,unsigned int port_number,const char *unix_socket_name,unsigned int flags);//連接MYSQL服務(wù)器,里面的參數(shù)應(yīng)該很清楚了,一般port_number和unix_socket_name的值為0和NULL。例如:
mysql_real_connect(conn_ptr,"localhost","sagely","secret","ra",0,NULL,0);
???? void mysql_close(MYSQL *connection);關(guān)閉一個(gè)連接。
3,????? 執(zhí)行SQL語(yǔ)句
mysql_select_db(MYSQL *connection,const char *db_name);選定某個(gè)數(shù)據(jù)庫(kù)。
???? int mysql_query(MYSQL *connection,const char *query)//他將執(zhí)行query語(yǔ)句,運(yùn)行成功將返回0,例如mysql_query(conn_ptr, Create table cert_info(...),將創(chuàng)建一個(gè)名為cert_info的表,幾乎所有的SQL語(yǔ)句都能這么執(zhí)行。呵呵,是不是顯得很簡(jiǎn)單,他就和命令行中輸入的SQL語(yǔ)句差不多。在使用上面函數(shù)的時(shí)候一般會(huì)使用
???? my_ulonglong mysql_affected_rows(MYSQL *connection),這個(gè)函數(shù)返回的是mysql_query對(duì)進(jìn)行改動(dòng)的行的數(shù)量。
4,????? 處理檢索到的數(shù)據(jù)
當(dāng)我們可以執(zhí)行SQL語(yǔ)句以后,那么就很容易執(zhí)行增加刪除修改等操作,但是假若檢索出來(lái)的數(shù)據(jù)存儲(chǔ)在哪里呢?
???? MYSQL_RES *mysql_use_result(MYSQL *connection)這個(gè)函數(shù)得到一個(gè)連接對(duì)象返回一個(gè)結(jié)果集合指針,出錯(cuò)時(shí)返回NULL。不過(guò)他只是返回一個(gè)集合對(duì)象初始化來(lái)接收數(shù)據(jù),并沒(méi)有將任何檢索到的數(shù)據(jù)返回到結(jié)果集合中。
???? MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)這個(gè)函數(shù)獲得mysql_use_resul得到的結(jié)果結(jié)構(gòu)體,并從中檢索單個(gè)行,并返回分配給行結(jié)構(gòu)體的數(shù)據(jù),沒(méi)有更多數(shù)據(jù)或出錯(cuò)時(shí),返回NULL。
???? Unsigned int mysql_field_count(MYSQL *connection)它得到一個(gè)連接對(duì)象并返回在集合中字段的數(shù)目。
于是有上面的基礎(chǔ)我們就可以理解下面這段了:(沒(méi)有錯(cuò)誤處理)
mysql_init(&conn_ptr);
mysql_real_connect(conn_ptr,"localhost","sagely","secret","ra",0,NULL,0);
mysql_query(conn_ptr,"SELECT * form usr_info);
res_ptr=mysql_use_result(&conn_ptr);
sqlrow=mysql_fetch_row(res_ptr);
for(int i=0;i<mysql_field_count(&conn_ptr);i++){printf("%s ",sqlrow);}
???? MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)它返回的是列的信息,比如列的名稱,列所在表名稱等等,有了這個(gè)就可以將列標(biāo)題與數(shù)據(jù)想對(duì)應(yīng)起來(lái)了。
|
? |
本文主要包括二個(gè)部分,第一部分重點(diǎn)介紹在VC中,怎么樣采用sizeof來(lái)求結(jié)構(gòu)的大小,以及容易出現(xiàn)的問(wèn)題,并給出解決問(wèn)題的方法,第二部分總結(jié)出VC中sizeof的主要用法。
1、 sizeof應(yīng)用在結(jié)構(gòu)上的情況
請(qǐng)看下面的結(jié)構(gòu):
struct MyStruct
{
double dda1;
char dda;
int type
};
對(duì)結(jié)構(gòu)MyStruct采用sizeof會(huì)出現(xiàn)什么結(jié)果呢?sizeof(MyStruct)為多少呢?也許你會(huì)這樣求:
sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13
但是當(dāng)在VC中測(cè)試上面結(jié)構(gòu)的大小時(shí),你會(huì)發(fā)現(xiàn)sizeof(MyStruct)為16。你知道為什么在VC中會(huì)得出這樣一個(gè)結(jié)果嗎?
其實(shí),這是VC對(duì)變量存儲(chǔ)的一個(gè)特殊處理。為了提高CPU的存儲(chǔ)速度,VC對(duì)一些變量的起始地址做了“對(duì)齊”處理。在默認(rèn)情況下,VC規(guī)定各成員變量存放的起始地址相對(duì)于結(jié)構(gòu)的起始地址的偏移量必須為該變量的類型所占用的字節(jié)數(shù)的倍數(shù)。下面列出常用類型的對(duì)齊方式(vc6.0,32位系統(tǒng))。
類型 對(duì)齊方式(變量存放的起始地址相對(duì)于結(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)的順序依次申請(qǐng)空間,同時(shí)按照上面的對(duì)齊方式調(diào)整位置,空缺的字節(jié)VC會(huì)自動(dòng)填充。同時(shí)VC為了確保結(jié)構(gòu)的大小為結(jié)構(gòu)的字節(jié)邊界數(shù)(即該結(jié)構(gòu)中占用最大空間的類型所占用的字節(jié)數(shù))的倍數(shù),所以在為最后一個(gè)成員變量申請(qǐng)空間后,還會(huì)根據(jù)需要自動(dòng)填充空缺的字節(jié)。
下面用前面的例子來(lái)說(shuō)明VC到底怎么樣來(lái)存放結(jié)構(gòu)的。
struct MyStruct
{
double dda1;
char dda;
int type
};
為上面的結(jié)構(gòu)分配空間的時(shí)候,VC根據(jù)成員變量出現(xiàn)的順序和對(duì)齊方式,先為第一個(gè)成員dda1分配空間,其起始地址跟結(jié)構(gòu)的起始地址相同(剛好偏移量0剛好為sizeof(double)的倍數(shù)),該成員變量占用sizeof(double)=8個(gè)字節(jié);接下來(lái)為第二個(gè)成員dda分配空間,這時(shí)下一個(gè)可以分配的地址對(duì)于結(jié)構(gòu)的起始地址的偏移量為8,是sizeof(char)的倍數(shù),所以把dda存放在偏移量為8的地方滿足對(duì)齊方式,該成員變量占用sizeof(char)=1個(gè)字節(jié);接下來(lái)為第三個(gè)成員type分配空間,這時(shí)下一個(gè)可以分配的地址對(duì)于結(jié)構(gòu)的起始地址的偏移量為9,不是sizeof(int)=4的倍數(shù),為了滿足對(duì)齊方式對(duì)偏移量的約束問(wèn)題,VC自動(dòng)填充3個(gè)字節(jié)(這三個(gè)字節(jié)沒(méi)有放什么東西),這時(shí)下一個(gè)可以分配的地址對(duì)于結(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ù),所以沒(méi)有空缺的字節(jié)需要填充。所以整個(gè)結(jié)構(gòu)的大小為:sizeof(MyStruct)=8+1+3+4=16,其中有3個(gè)字節(jié)是VC自動(dòng)填充的,沒(méi)有放任何有意義的東西。
下面再舉個(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)分配空間的。(簡(jiǎn)單說(shuō)明)
struct MyStruct
{
char dda;//偏移量為0,滿足對(duì)齊方式,dda占用1個(gè)字節(jié);
double dda1;//下一個(gè)可用的地址的偏移量為1,不是sizeof(double)=8
//的倍數(shù),需要補(bǔ)足7個(gè)字節(jié)才能使偏移量變?yōu)?(滿足對(duì)齊
//方式),因此VC自動(dòng)填充7個(gè)字節(jié),dda1存放在偏移量為8
//的地址上,它占用8個(gè)字節(jié)。
int type;//下一個(gè)可用的地址的偏移量為16,是sizeof(int)=4的倍
//數(shù),滿足int的對(duì)齊方式,所以不需要VC自動(dòng)填充,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自動(dòng)填充的,沒(méi)有放任何有意義的東西。
VC對(duì)結(jié)構(gòu)的存儲(chǔ)的特殊處理確實(shí)提高CPU存儲(chǔ)變量的速度,但是有時(shí)候也帶來(lái)了一些麻煩,我們也屏蔽掉變量默認(rèn)的對(duì)齊方式,自己可以設(shè)定變量的對(duì)齊方式。
VC中提供了#pragma pack(n)來(lái)設(shè)定變量以n字節(jié)對(duì)齊方式。n字節(jié)對(duì)齊就是說(shuō)變量存放的起始地址的偏移量有兩種情況:第一、如果n大于等于該變量所占用的字節(jié)數(shù),那么偏移量必須滿足默認(rèn)的對(duì)齊方式,第二、如果n小于該變量的類型所占用的字節(jié)數(shù),那么偏移量為n的倍數(shù),不用滿足默認(rèn)的對(duì)齊方式。結(jié)構(gòu)的總大小也有個(gè)約束條件,分下面兩種情況:如果n大于所有成員變量類型所占用的字節(jié)數(shù),那么結(jié)構(gòu)的總大小必須為占用空間最大的變量占用的空間數(shù)的倍數(shù);
否則必須為n的倍數(shù)。下面舉例說(shuō)明其用法。
#pragma pack(push) //保存對(duì)齊狀態(tài)
#pragma pack(4)//設(shè)定為4字節(jié)對(duì)齊
struct test
{
char m1;
double m4;
int m3;
};
#pragma pack(pop)//恢復(fù)對(duì)齊狀態(tài)
以上結(jié)構(gòu)的大小為16,下面分析其存儲(chǔ)情況,首先為m1分配空間,其偏移量為0,滿足我們自己設(shè)定的對(duì)齊方式(4字節(jié)對(duì)齊),m1占用1個(gè)字節(jié)。接著開(kāi)始為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。(請(qǐng)讀者自己分析)
2、 sizeof用法總結(jié)
在VC中,sizeof有著許多的用法,而且很容易引起一些錯(cuò)誤。下面根據(jù)sizeof后面的參數(shù)對(duì)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ù)組或指針。下面舉例說(shuō)明.
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)成員不對(duì)結(jié)構(gòu)或者類的大小產(chǎn)生影響,因?yàn)殪o態(tài)變量的存儲(chǔ)位置與結(jié)構(gòu)或者類的實(shí)例地址無(wú)關(guān)。
第二、沒(méi)有成員變量的結(jié)構(gòu)或類的大小為1,因?yàn)楸仨毐WC結(jié)構(gòu)或類的每一
個(gè)實(shí)例在內(nèi)存中都有唯一的地址。
下面舉例說(shuō)明,
Class Test{int a;static double c};//sizeof(Test)=4.
Test *s;//sizeof(s)=4,s為一個(gè)指針。
Class test1{ };//sizeof(test1)=1;
D. 參數(shù)為其他。下面舉例說(shuō)明。
int func(char s[5]);
{
cout< //數(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的分配變量的分配策略,這樣的話可以避免一些錯(cuò)誤。
|
|
--
建表語(yǔ)句
CREATE
?
TABLE
?
[
MyTable
]
?(
????
[
MyId
]
?
[
varchar
]
?(
50
)?COLLATE?Chinese_PRC_CI_AS?
NULL
?,
????
[
MyName
]
?
[
varchar
]
?(
50
)?COLLATE?Chinese_PRC_CI_AS?
NULL
?
)?
ON
?
[
PRIMARY
]
GO
--
得到新的編號(hào)(不考慮補(bǔ)號(hào))
create
?
function
?f_NextID(
@myDate
?
datetime
)
Returns
?
char
(
12
)
as
begin
?
????
Declare
?
@temp
?
char
(
6
)
?????
Declare
?
@ret
?
char
(
12
)
????
set
?
@temp
=
Substring
(
Convert
(
char
,
@myDate
),
9
,
2
)
+
Substring
(
Convert
(
char
,
@myDate
),
1
,
2
)
+
Substring
(
Convert
(
char
,
@myDate
),
4
,
2
)
????
if
(
@temp
?
in
?(
SELECT
?
distinct
?myid
=
left
(myid,
6
)?
FROM
?mytable?
WITH
(XLOCK,PAGLOCK)))
????????????
Select
?
@ret
=
@temp
+
right
(
1000001
+
Isnull
(
Max
(
Right
(MyID,
6
)),
0
),
6
)?
from
?Mytable?
with
(xlock,paglock)?
where
?
@temp
=
left
(MyID,
6
)
????
else
????????
Select
?
@ret
=
@temp
+
'
000001
'
?
from
?Mytable?
with
(xlock,paglock)
????
return
?
@ret
end
?
GO
drop
?
table
?MyTable
--
建表語(yǔ)句
CREATE
?
TABLE
?
[
MyTable
]
?(
????
[
MyId
]
?
[
varchar
]
?(
50
)?COLLATE?Chinese_PRC_CI_AS?
NULL
?,
????
[
MyName
]
?
[
varchar
]
?(
50
)?COLLATE?Chinese_PRC_CI_AS?
NULL
?
)?
ON
?
[
PRIMARY
]
GO
--
得到新的編號(hào)(融合了補(bǔ)號(hào)處理)
create
?
FUNCTION
?f_NextNewID(
@myDate
?
datetime
)
RETURNS
?
char
(
12
)
AS
BEGIN
????
Declare
?
@temp
?
char
(
6
)
?????
Declare
?
@ret
?
char
(
12
)
????
set
?
@temp
=
Substring
(
Convert
(
char
,
@myDate
),
9
,
2
)
+
Substring
(
Convert
(
char
,
@myDate
),
1
,
2
)
+
Substring
(
Convert
(
char
,
@myDate
),
4
,
2
)
????
DECLARE
?
@r
?
char
(
12
)
????
????
SELECT
?
@r
=
@temp
+
RIGHT
(
1000001
+
MIN
(MyId),
6
)
????
FROM
(
????????
SELECT
?MyId
=
RIGHT
(MyId,
6
)?
FROM
?MyTable?
WITH
(XLOCK,PAGLOCK)
????????
UNION
?
ALL
?
SELECT
?
0
????)a?
??
WHERE
?
NOT
?
EXISTS
(
????????
SELECT
?
*
?
FROM
?MyTable??
WITH
(XLOCK,PAGLOCK)
????????
WHERE
?MyId
=
@temp
+
RIGHT
(
1000001
+
a.myID,
6
))
????
RETURN
(
@r
)
END
GO
--
測(cè)試語(yǔ)句(可改變時(shí)間測(cè)試一下)
insert
?MyTable?
values
?(dbo.f_NextNewID(
GetDate
()),
'
one
'
)
insert
?MyTable?
values
?(dbo.f_NextNewID(
GetDate
()),
'
two
'
)
insert
?MyTable?
values
?(dbo.f_NextNewID(
GetDate
()),
'
three
'
)
insert
?MyTable?
values
?(dbo.f_NextNewID(
GetDate
()),
'
four
'
)
insert
?MyTable?
values
?(dbo.f_NextNewID(
GetDate
()),
'
five
'
)
insert
?MyTable?
values
?(dbo.f_NextNewID(
GetDate
()),
'
six
'
)
Select
?
*
?
from
?MyTable?
order
?
by
?MyId
GO
delete
?MyTable?
where
?myId
=
'
060629000002
'
delete
?MyTable?
where
?myId
=
'
060629000005
'
Select
?
*
?
from
?MyTable?
order
?
by
?MyId
Go
insert
?MyTable?
values
?(dbo.f_NextNewID(
GetDate
()),
'
nexttwo
'
)
insert
?MyTable?
values
?(dbo.f_NextNewID(
GetDate
()),
'
nextfive
'
)
Select
?
*
?
from
?MyTable?
order
?
by
?MyId
GO
§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
SQL下測(cè)試成功