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

Effective STL (2)——vector 和 string

1.vector和string優(yōu)先于動態(tài)分配的數(shù)組。

2.使用reserve來避免不必要的重新分配
    關(guān)于stl容器會自動增長以便容納下你放入其中的數(shù)據(jù),只要沒有超過它們的最大限制就可以。對于vector和string,增長過程是這樣實現(xiàn)的:每當(dāng)需要更多空間時,就調(diào)用與realloc類似的操作。這一類似于relloc的操作分為如下4部分:
        (1)分配一塊大小為當(dāng)前容量的某個倍數(shù)的新內(nèi)存。在大多數(shù)實現(xiàn)中,vector和string的容量每次以2的倍數(shù)增長,即每當(dāng)容器需要擴(kuò)張時,它們的容量即加倍。
         (2)把容器的所有元素從舊的內(nèi)存復(fù)制到新的內(nèi)存中。
         (3)析構(gòu)掉舊內(nèi)存中的元素
         (4)釋放舊內(nèi)存
    reserve成員函數(shù)能使你把重新分配的次數(shù)減少到最低限度,從而避免了重新分配和指針迭代器引用失效帶來的開銷。
    簡單概括一下四個相互關(guān)聯(lián)、但有時會被混淆的成員函數(shù)。在標(biāo)準(zhǔn)容器中,只有vector和string提供了所有這四個函數(shù):
         (1)size() 告訴你容器中有多少個元素,它不會告訴你該容器為自己所包含的元素分配了多少內(nèi)存。
         (2)capacity()告訴你容器利用已經(jīng)分配的內(nèi)存可以容納多少元素。這是容器所能容納的元素總數(shù),而不是它還能容納多少個元素。如果你想知道一個vector有多少未被使用的內(nèi)存,就得從capacity()中減去size()。如果size和capacity返回同樣的值,就說明容器中不再有剩余空間了,因此下一個插入操作(push_back)將導(dǎo)致上面所提到的重新分配過程。
         (3)resize(xx)強迫容器改變到包含n個元素的狀態(tài)。在調(diào)用resize之后,size將返回n。如果n比當(dāng)前的大?。╯ize)要小,則容器尾部的元素將會被析構(gòu)掉。如果n比當(dāng)前的大小要大,則通過默認(rèn)構(gòu)造函數(shù)創(chuàng)建的新元素將被添加到容器的末尾。如果n比當(dāng)前的容量要大,那么在添加元素之前,將先重新分配內(nèi)存。
          (4)reserve(xx)強迫容器把它的容量變?yōu)橹辽偈莕,前提是n不小于當(dāng)前的大小。這通常會導(dǎo)致重新分配,因為容量需要增加。(如果n比當(dāng)前的容量小,則vector什么也不做)
       因此,避免重新分配的關(guān)鍵在于,盡早的只用reserve,把容器的容量設(shè)為足夠大的值,最好是在容器剛被構(gòu)造出來之后就使用reserve。

3.注意string實現(xiàn)的多樣性
   
4.了解如何把vector和string數(shù)據(jù)傳給舊的API

5.使用“swap技巧”除去多余的容量。

6.避免使用vector<bool>
    vector<bool>不是一個stl容器,也不存儲bool。在一個典型的實現(xiàn)中,儲存在vector中的每個bool僅占一個二進(jìn)制位,一個8位的字節(jié)可容納8g個“bool”。在內(nèi)部vector<bool>使用了與位域一樣的思想,來表示它所存儲的那些bool;實際上只是假裝存儲了這些bool。
     vector<bool>不完全滿足STL容器的要求;你最好不要使用它;你可以使用deque<bool>和bitset來替代它,這兩個數(shù)據(jù)結(jié)構(gòu)幾乎能做vector<bool>所能做的一切事情。

posted @ 2014-04-20 14:10 Daywei 閱讀(2531) | 評論 (0)編輯 收藏

Effective STL (1)

 慎重選擇容器類型
 標(biāo)準(zhǔn)序列容器:vector string deque list
 標(biāo)準(zhǔn)關(guān)聯(lián)容器 : set multiset map multimap
 非標(biāo)準(zhǔn)序列容器: slist rope. slist 是一個單向鏈表,rope 本質(zhì)上市一個“重型”string
 非標(biāo)準(zhǔn)的關(guān)聯(lián)容器 hash_set hash_nultiset hash_map hash_multimap vector 作為string的替代。 vector 作為標(biāo)準(zhǔn)關(guān)聯(lián)容器的替代
 幾種標(biāo)準(zhǔn)的非STL容器 包括 數(shù)組、bitset valarray stack queue 和 priority_queue

 容器可分類為 連續(xù)內(nèi)存容器和基于節(jié)點的容器

連續(xù)內(nèi)存容器把它的元素存放在一塊或多塊(動態(tài)分配的)內(nèi)存中,每塊內(nèi)存中存有多個元素。當(dāng)有新元素插入或已有的元素被刪除時,同一內(nèi)存塊中的其他元素要向前或向后移動,以便為新元素讓出空間,或者填充被刪除元素所留下的空隙。
基于節(jié)點的容器在每一個(動態(tài)分配的)內(nèi)存塊中只存放一個元素。容器中元素的插入或刪除只影響到指向節(jié)點的指針,而不影響節(jié)點本身的內(nèi)容,所以當(dāng)有插入或刪除操作時,元素的值不需要移動。

你是否需要在容器的任意位置插入新元素?如果需要,就選擇序列容器;關(guān)聯(lián)容器是不行的。
你是否關(guān)心容器中的元素師排序的?如果不關(guān)心,則哈希容器室一個可行的選擇方案;否則,你要避免哈希容器。
容器中數(shù)據(jù)的布局是否需要和C兼容?如果需要兼容,就只能選擇vector。
元素的查找速度是否是關(guān)鍵的考慮因素?如果是,就要考慮哈希容器、排序的vector和標(biāo)準(zhǔn)關(guān)聯(lián)容器——或許這就是優(yōu)先順序。


確保容器中的對象拷貝正確而高效

調(diào)用empty而不是檢查size()是否為 0
理由很簡單:empty對所有的標(biāo)準(zhǔn)容器都是常數(shù)時間操作,而對一些list實現(xiàn),size耗費線性時間。由于list所獨有的鏈接操作。

區(qū)間成員函數(shù)優(yōu)先于與之對應(yīng)的單元素成員函數(shù)。

如果容器中包含了通過new操作創(chuàng)建的指針,切記在容器對象析構(gòu)前將指針delete掉。切勿創(chuàng)建包含auto_ptr的容器對象。問題的根源只是在于auto_ptr不是這樣的智能指針。
永遠(yuǎn)都不要錯誤的認(rèn)為:你可以通過創(chuàng)建auto_ptr的容器使指針被自動刪除。

慎重選擇刪除元素的方法
erase是指向緊隨被刪除元素的下一個元素的有效迭代器。


要刪除容器中有特定值得所有對象
  如果容器使vector、string或deque,則使用earse-remove習(xí)慣用法。
  如果容器是list,則使用list::remove
  如果容器是一個標(biāo)準(zhǔn)關(guān)聯(lián)容器,則使用它的erase成員函數(shù)。

要刪除容器中滿足特定判別式(條件)的所有對象
  如果容器是vector、string或deque,則使用erase-remove_if的習(xí)慣用法。
  如果容器是list,則使用list::remove_if。
  如果容器使一個標(biāo)準(zhǔn)關(guān)聯(lián)容器,則使用remove_copy_if和swap,或者寫一個循環(huán)來遍歷容器中的元素,記住當(dāng)把迭代器傳給erase時,要對它進(jìn)行后綴遞增。

要在循環(huán)內(nèi)部做某些(除了刪除對象之外的)操作
  如果容器使一個標(biāo)準(zhǔn)序列容器,則寫一個循環(huán)來遍歷容器中的元素,記住每次調(diào)用erase時,要用它的返回值更新迭代器。
  如果容器是一個標(biāo)準(zhǔn)關(guān)聯(lián)容器,則寫一個循環(huán)來遍歷容器中的元素,記住當(dāng)把迭代器傳給erase時,要對迭代器作后綴遞
增。

切勿對STL容器的線程安全性有不切實際的依賴。

  你不能指望STL庫會把你從手工同步控制中解脫出來,而且你不能依賴于任何線程的支持。
  在容器所返回的每個迭代器的生存期結(jié)束前,都鎖住容器
  對于作用于容器的每個算法,都鎖住該容器,直到算法結(jié)束。  多個線程讀是安全的
  多個線程對不同的容器作寫入操作時安全的。
  對容器成員函數(shù)的每次調(diào)用,都鎖住容器直到調(diào)用結(jié)束。

posted @ 2014-04-04 21:10 Daywei 閱讀(2137) | 評論 (0)編輯 收藏

vim使用總結(jié)ing

VIM官網(wǎng):
http://www.vim.org/
里面已經(jīng)包含了很多插件,可隨意配置。
先是一些vim基本配置設(shè)置

vim語法高亮顯示和自動縮進(jìn)
      
1、配置文件的位置
在目錄 /etc/ 下面,有個名為vimrc的文件,這是系統(tǒng)中公共的vim配置文件,對所有用戶都有效。而在每個用戶的主目錄下,都可以自己建立私有的配置文件,命名為:“.vimrc”。例如,/root目錄下,通常已經(jīng)存在一個.vimrc文件。
    2、設(shè)置語法高亮顯示
1) 打開vimrc,添加以下語句來使得語法高亮顯示:
syntax on
2) 如果此時語法還是沒有高亮顯示,那么在/etc目錄下的profile文件中添加以下語句:
export TERM=xterm-color
      
    3、設(shè)置Windows風(fēng)格的C/C++自動縮進(jìn)(添加以下set語句到vimrc中)
              1)設(shè)置(軟)制表符寬度為4:
                            set tabstop=4
                            set softtabstop=4
              2)設(shè)置縮進(jìn)的空格數(shù)為4
                          set shiftwidth=4
              3)設(shè)置自動縮進(jìn):即每行的縮進(jìn)值與上一行相等;使用 noautoindent 取消設(shè)置:
set autoindent
              4)設(shè)置使用 C/C++ 語言的自動縮進(jìn)方式:
                          set cindent
              5)設(shè)置C/C++語言的具體縮進(jìn)方式(以我的windows風(fēng)格為例):
                            set cinoptions={0,1s,t0,n-2,p2s,(03s,=.5s,>1s,=1s,:1s
              6)如果想在左側(cè)顯示文本的行號,可以用以下語句:
                          set nu
              7)最后,如果沒有下列語句,就加上吧:
if &term=="xterm"
set t_Co=8
             set t_Sb=^[[4%dm
set t_Sf=^[[3%dm
              endif

安裝ctags+taglist
1.ctags
(1)到http://ctags.sourceforge.net/下載ctags源碼ctags-5.6.tar.gz
http://prdownloads.sourceforge.net/ctags/ctags-5.6.tar.gz
(2)解壓并安裝
tar zxvf ctags-5.6.tar.gz
cd ctags-5.6
./configure && make && make install
(3)使用
[/home/brimmer/src]$ ctags -R

"-R"表示遞歸創(chuàng)建,也就包括源代碼根目錄下的所有子目錄下的源程序。"tags"文件中包括這些對象的列表:
l 用#define定義的宏
l 枚舉型變量的值
l 函數(shù)的定義、原型和聲明
l 名字空間(namespace)
l 類型定義(typedefs)
l 變量(包括定義和聲明)
l 類(class)、結(jié)構(gòu)(struct)、枚舉類型(enum)和聯(lián)合(union)
l 類、結(jié)構(gòu)和聯(lián)合中成員變量或函數(shù)
VIM用這個"tags"文件來定位上面這些做了標(biāo)記的對象,下面介紹一下定位這些對象的方法:

1) 用命令行。在運行vim的時候加上"-t"參數(shù),例如:
[/home/brimmer/src]$ vim -t foo_bar
這個命令將打開定義"foo_bar"(變量或函數(shù)或其它)的文件,并把光標(biāo)定位到這一行。
2) 在vim編輯器內(nèi)用":ta"命令,例如:
:ta foo_bar
3) 最方便的方法是把光標(biāo)移到變量名或函數(shù)名上,然后按下"Ctrl-]"。用"Ctrl-o"退回原來的地方。
注意:運行vim的時候,必須在"tags"文件所在的目錄下運行。否則,運行vim的時候還要用":set tags="命令設(shè)定"tags"文件的路徑,這樣vim才能找到"tags"文件。

在函數(shù)中移動光標(biāo)
[{ 轉(zhuǎn)到上一個位于第一列的"{"
}] 轉(zhuǎn)到下一個位于第一列的"{"
{ 轉(zhuǎn)到上一個空行
} 轉(zhuǎn)到下一個空行 ([ and ] 也分別是兩個指令)
gd 轉(zhuǎn)到當(dāng)前光標(biāo)所指的局部變量的定義
* 轉(zhuǎn)到當(dāng)前光標(biāo)所指的單詞下一次出現(xiàn)的地方
# 轉(zhuǎn)到當(dāng)前光標(biāo)所指的單詞上一次出現(xiàn)的地方
Vim 的創(chuàng)造者是一名計算機(jī)程序員,因此這就不奇怪 Vim 中有許多幫助編寫程序的功能:
跳轉(zhuǎn)到標(biāo)識符被定義和使用的地方;在另一個窗口中預(yù)覽有關(guān)的聲明等等。
(ctags使用部分參考了 文章“ctags和vim”,原文在
http://hi.baidu.com/original/blog/item/2cf8d53f00b7fcc27d1e71f0.html
更多使用也請參考原文)


2. taglist
能夠列出源文件中的tag(function, class, variable, etc)并跳轉(zhuǎn).
注意:taglist依賴于ctags,所以要先裝ctags,否則taglist裝了也沒法用!
(1)到http://vim.sourceforge.net/scripts/script.php?script_id=273
下載taglist_42.zip,即
http://vim.sourceforge.net/scripts/download_script.php?src_id=6416
(2)解壓得到兩個文件
# unzip -d taglist taglist_42.zip
# cd taglist
# tree
.
|-- doc
| `-- taglist.txt
`-- plugin
`-- taglist.vim
(3)安裝
cp doc/taglist.txt /usr/share/vim/vim61/doc/
cp plugin/taglist.vim /usr/share/vim/vim61/plugin/
(4)配置和使用
cd /usr/share/vim/vim61/doc/
啟動vim,用 “:helptags .”來配置好幫助文件
重啟vim,用“:TlistToggle”來打開和關(guān)閉taglist窗口。
可以用“:help taglist”來獲得更多幫助信息

set tags=./tags,./../tags,./http://www.cnblogs.com/tags,./**/tags
                   
let Tlist_Use_Left_Window=1
let Tlist_Auto_Update=1
let Tlist_Exit_OnlyWindow=1
let Tlist_Show_One_File=1
nmap <F7> :TlistToggle <CR>
其次安裝配置基本的插件
1.安裝好Vim和Vim的基本插件。在ubuntu下這些使用apt-get安裝即可:
lingd@ubuntu:~/arm$sudo apt-get install vim vim-scripts vim-doc
其中vim-scripts是vim的一些基本插件,包括語法高亮的支持、縮進(jìn)等等。
vim中文幫助文檔tar包下載地址:
http://sourceforge.net/projects/vimcdoc/files/vimcdoc/
解壓后其中有個doc文件夾, 將其中的內(nèi)容全部復(fù)制到~/.vim/doc, 或者vim安裝目錄下的doc目錄中, 此時vim中的help信息已經(jīng)是中文的了.
網(wǎng)頁版中文幫助文檔網(wǎng)址http://vimcdoc.sourceforge.net/doc/help.html
首頁就時vim幫助文檔的目錄,閱讀起來更方便有效、更有針對性!

2.管理vim插件——vim-addons
通過vim-addons,我們可以管理vim插件。我們在sudo apt-get install vim vim-scripts vim-doc時,一般會自動安裝上vim-addons。若未安裝可通過sudo apt-get install vim-addon-manager手動安裝。安裝完成后,就可以用vim-addons管理vim插件了。
# 系統(tǒng)中已有的vim-scripts中包含的插件及其狀態(tài):
lingd@ubuntu:~$ vim-addons status
# Name                     User Status  System Status
align                       removed       removed      
alternate                   removed       removed      
bufexplorer                 removed       removed      
calendar                    removed       removed      
closetag                    removed       removed      
colors sampler pack         removed       removed      
cvsmenu                     removed       removed      
debPlugin                   removed       removed      
detectindent                removed       removed      
doxygen-toolkit             removed       removed      
editexisting                removed       removed      
enhanced-commentify         removed       removed      
gnupg                       removed       removed      
info                        removed       removed      
justify                     removed       removed      
lbdbq                       removed       removed      
markdown-syntax             removed       removed      
matchit                     removed       removed      
minibufexplorer             installed     removed      
nerd-commenter              removed       removed      
omnicppcomplete             installed     removed      
po                          removed       removed      
project                     installed     removed      
python-indent               removed       removed      
secure-modelines            removed       removed      
snippetsEmu                 removed       removed      
sokoban                     removed       removed      
supertab                    removed       removed      
surround                    removed       removed      
taglist                     installed     removed      
tetris                      removed       removed      
utl                         removed       removed      
vcscommand                  removed       removed      
vimplate                    removed       removed      
whatdomain                  removed       removed      
winmanager                  removed       removed      
xmledit                     removed       removed   




Reference:
vim配置為C/C++開發(fā)環(huán)境
一步步將vim改造成C/C++開發(fā)環(huán)境(IDE)
              

posted @ 2013-04-06 12:12 Daywei 閱讀(1209) | 評論 (0)編輯 收藏

How to create a Simple Lock Framework for C++ Synchronization

How to create a Simple Lock Framework for C++ Synchronization

posted @ 2012-08-21 14:37 Daywei 閱讀(783) | 評論 (0)編輯 收藏

C、C++寫二進(jìn)制數(shù)據(jù)到mysql的Blob字段

-- 引子--

由于調(diào)試需要,需直接往數(shù)據(jù)庫里寫入二進(jìn)制數(shù)據(jù)。本來這些數(shù)據(jù)是由上層軟件來寫的,用的是C#。為了熟悉C語言的數(shù)據(jù)庫操作,還是決定用C來寫這段調(diào)試代碼。

概況:

表名:Task

涉及的字段及屬性:

NumDestint(11) 用于存儲目標(biāo)數(shù)目

destIDs: blob 用于存儲具體的目標(biāo)ID

廢話不多說,入正題。



--二進(jìn)制數(shù)據(jù)寫入--

二進(jìn)制數(shù)據(jù)最為常見的就是圖片等一些文件信息。雖然我這里不是這類型信息,但確實是二進(jìn)制數(shù)據(jù)。

具體步驟:

1、 定義一個buffer(如數(shù)組)來存儲sql語句

2、 把涉及到二進(jìn)制數(shù)據(jù)之前的sql語句添加到buffer中,可用sprintfstrcpy等。

3、 mysql_real_escape_string()函數(shù)添加二進(jìn)制數(shù)據(jù)到buffer中。

4、 加上剩余的sql語句,形成完整的sql語句。

5、 利用mysql_real_query()函數(shù)來執(zhí)行sql語句。

具體代碼如下:


#include <stdio.h>
#include <stdlib.h>
#include <mysql/mysql.h>
#include <stdint.h>
#include <string.h>

int main(int argc, char *argv[])
{
MYSQL mysql;
char sql[256], *end;
int index, i;
uint32_t *destIDs;

if(argc != 2)
{
printf("enter error!\n");
exit(1);
}
index = atoi(argv[1]);
printf("index: %d\n", index);
destIDs = (uint32_t *)malloc(index * sizeof(uint32_t));
if(destIDs == NULL)
printf("malloc error\n");
for(i=0; i<index; i++)
destIDs[i] = i + 1;
mysql_init(&mysql);
if(!(mysql_real_connect(&mysql, "localhost", "root", "654321", "dbname", 0, NULL, 0)))
{
fprintf(stderr, "Couldn't connect to engine!\n%s\n", mysql_error(&mysql));
perror("");
exit(1);
}

sprintf(sql, "INSERT INTO Task(NumDest, DestIDs) VALUE (%u, ", index );
end = sql + strlen(sql);
*end++ = '\'';
end += mysql_real_escape_string(&mysql, end,(char *)destIDs, index*sizeof(uint32_t));
*end++ = '\'';
*end++ = ')';

printf("end - sql: %d\n", (unsigned int)(end - sql));

if(mysql_real_query(&mysql, sql, (unsigned int)(end - sql)))
{
fprintf(stderr, "Query failed (%s)\n", mysql_error(&mysql));
exit(1);
}
mysql_close(&mysql);
exit(0);
#endif
return 0;
}




--讀取二進(jìn)制文件--

對于二進(jìn)制文件的讀取,也類似。

具體步驟:

1,構(gòu)造查詢字串.

2,執(zhí)行mysql _query查詢. (網(wǎng)上有說用mysql_real_query,未實驗)

3,mysql_store_result存儲結(jié)果.

4,mysql_fetch_row取出一條記錄處理.

具體代碼如下:


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <mysql/mysql.h>
#include <string.h>

int main(void)
{
int ret, i;
char sql[256];
MYSQL mysql;
MYSQL_RES *result;
MYSQL_ROW row;
uint32_t *destIDs, *temp;
unsigned int destNum = 0;

mysql_init(&mysql);
if(!(mysql_real_connect(&mysql, "localhost", "root", "654321", "dbname", 0, NULL, 0)))
{
fprintf(stderr, "Couldn't connect to engine!\n%s\n",
mysql_error(&mysql));
perror("");
exit(1);
}

sprintf(sql,
"SELECT TaskID, NumDest, DestIDs FROM Task");
ret = mysql_query(&mysql, sql);
if(ret != 0)
{
printf( "Failed to query task table: %s\n",
mysql_error(&mysql));
return ret;
}

result = mysql_store_result(&mysql);
if(result == NULL)
{
ret = mysql_errno(&mysql);
printf( "Failed to store query result from task table:%s\n",
mysql_error(&mysql));
return ret;
}

if((row = mysql_fetch_row(result)) != NULL)
{
sscanf(row[1], "%u", &destNum);

destIDs = (uint32_t *)malloc(destNum * sizeof(uint32_t));
if(destIDs == NULL)
{
printf("malloc error!\n");
exit(1);
}
memcpy(destIDs, row[2], destNum * sizeof(uint32_t));
}

mysql_free_result(result);

printf("destNum: %d\n", destNum);
temp = destIDs;
for(i=0; i<destNum; i++)
{
printf("destIDs[%d]:%d\t", i+1, *temp++);
}

return ret;
}


由于我這里可以根據(jù)NumDest獲取到二進(jìn)制的長度,所以不用再用函數(shù)去獲取。

據(jù)網(wǎng)上信息,獲取二進(jìn)制信息長度應(yīng)該這樣:“如果取出來的是二進(jìn)制的數(shù)據(jù),要確定它的長度,必須要用mysql_fetch_lengths函數(shù)取得其長度”


int num_fields = mysql_num_fields(result);
unsigned long *lengths = mysql_fetch_lengths(result);
for(i=0; i<num_fields; i++)
printf("Column: %u\t %lu bytes\n", i+1, lengths[i]);
destIDs = (uint32_t *)malloc(lengths[2]);
if(destIDs == NULL)
{
printf("malloc error!\n");
exit(1);
}
memcpy(destIDs, row[2], lengths[2]);





取二進(jìn)制數(shù)據(jù):

一樣的sql語句,查詢出來即可。只不過二進(jìn)制數(shù)據(jù)是個數(shù)據(jù)塊,需要得到數(shù)據(jù)塊的大小和數(shù)據(jù)指針。

bool CMySqlAccess::GetBinaryField(int nCol,char* &pDataOut,int& nDataLen)
{
if (m_ItemMySqlRow[nCol] != NULL)
{
unsigned long *FieldLength = mysql_fetch_lengths(m_pMySqlResult);
nDataLen = (int)FieldLength[nCol];
pDataOut = (char*)(m_ItemMySqlRow[nCol]);
return true;
}
else
{
return false;
}
}

像通常一樣查詢后,得到結(jié)果集,然后得到第nCol列結(jié)果,返回二進(jìn)制指針結(jié)果和二進(jìn)制長度。返回后必須立馬處理或者存儲一份。否則mysql將數(shù)據(jù)銷毀,指針?biāo)笖?shù)據(jù)則無效了。

存二進(jìn)制數(shù)據(jù):

mysql語句接受的sql語句都是string,以'\0'結(jié)尾的。如果冒然插入二進(jìn)制數(shù)據(jù)到sql語句中,要么報錯,要么存儲錯誤。此處可以通過mysql提供的函數(shù)將數(shù)據(jù)轉(zhuǎn)換一下即可。

char* CMySqlAccess::ConvertBinaryToString(char* pBinaryData,int nLen)
{
static char s_BinaryData[10240];
mysql_real_escape_string(m_pMySqlConn,s_BinaryData,pBinaryData,nLen);
return s_BinaryData;
}
上面這個函數(shù)只能單線程使用啊,將一塊二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為mysql可識別的string數(shù)據(jù)。這樣就直接可以通過mysql的sql語句insert,update來對blob數(shù)據(jù)進(jìn)行更新和插入了,sql語句用法不變。

用例:

std::ostringstream strSQL;
strSQL<<"INSERT INTO "<<m_strTableName<<"(roleid,playerdata,dynamicdata) VALUES("<<dwDBRoleID
<<",'"<<m_pDBAccess->ConvertBinaryToString(pData,nLen)<<"','')";
assert(m_pDBAccess);
m_pDBAccess->ExecuteSQL(strSQL.str());

playerdata是blob二進(jìn)制類型,pData是指向一個結(jié)構(gòu)體的指針,nLen是結(jié)構(gòu)體的大小。

上面就可以實現(xiàn)二進(jìn)制的存儲了。

 

方法二:

上面的方法,你會發(fā)現(xiàn),你每次都需要轉(zhuǎn)換數(shù)據(jù),傳指針,傳大小等一系列復(fù)雜操作,是不是順序很混亂,過程很繁雜。mysql也為你提供了另外一種方法,那就是MYSQL_BIND。將數(shù)據(jù)操作統(tǒng)一化,統(tǒng)一麻煩化。mysqlbind是一個結(jié)構(gòu)體,根據(jù)個人不同需求填充各個數(shù)據(jù)成員可以存儲任意類型數(shù)據(jù),當(dāng)然包括blob。

bool CMySqlAccess::SetBinaryField(std::string& strCondition,void* pDataIn,int nDataLen)
{
if( ! mysql_stmt_prepare( m_pMySqlStmt, strCondition.c_str(), strCondition.length() ) )
{
memset(&m_MySqlBind,0,sizeof(MYSQL_BIND));
m_MySqlBind.buffer_type = MYSQL_TYPE_BLOB;
(*m_MySqlBind.length) = nDataLen;
memcpy(m_MySqlBind.buffer,pDataIn,nDataLen);
if(!mysql_stmt_bind_param(m_pMySqlStmt, (MYSQL_BIND *)&m_MySqlBind))
{
if(!mysql_stmt_execute(m_pMySqlStmt))
{
return true;
}
}
}
int nRes=GetDBErrorCode();
CLogOutStream errLog(crazy::ERROR_LEVEL,THIS_CLASS_NAME);
errLog<<"MySql Query Failed:\""<<strCondition<<"\" ,ErrorCode:"<<nRes<<crazy::logEnd;
return false;
}

這個是對某一列blob數(shù)據(jù)進(jìn)行存操作。pDataIn和nDataLen分別是一個struct結(jié)構(gòu)體和結(jié)構(gòu)體大小。填充完畢mysqlbind之后即可對數(shù)據(jù)庫二進(jìn)制列進(jìn)行存儲了。可能你會問,沒有指定哪一列呢,對。哪一列是在strCondition語句里面的,這是一個預(yù)處理語句。在預(yù)處理語句里面,有一個符號: ? 。問號,問號的位置代表了mysqlbind數(shù)據(jù)對應(yīng)的位置。

INSERT INTO test_table(date_field, time_field, timestamp_field) VALUES(?,?,?)

上面這個語句,有3個問號,三個問號分別對應(yīng)test_table的三列.每個問號呢又對應(yīng)一個mysqlbind數(shù)據(jù)結(jié)構(gòu)。那么我們在mysql_stmt_bind_param函數(shù)調(diào)用時,就應(yīng)該傳入一個mysql_bind 數(shù)組。MYSQL_BIND m_MySqlBind[3].

填充整個數(shù)組數(shù)據(jù),即對應(yīng)三個問號內(nèi)容。

用例:
MYSQL_BIND bind[3];
MYSQL_STMT *stmt;

strmov(query, "INSERT INTO test_table(date_field, time_field, timestamp_field) VALUES(?,?,?");
//初始化stmt
stmt = mysql_stmt_init(mysql);
//預(yù)處理語句
mysql_stmt_prepare(mysql, query, strlen(query));
//初始化參數(shù)
bind[0].buffer_type= MYSQL_TYPE_DATE;
bind[0].buffer= (char *)&ts;
bind[0].is_null= 0;
bind[0].length= 0;
bind[1]= bind[2]= bind[0];
//綁定參數(shù)123
mysql_stmt_bind_param(stmt, bind);
//執(zhí)行預(yù)處理mysql語句
mysql_stmt_execute(stmt);

還沒看懂就個人去看mysql文檔了,其實里面講得很清楚,只要找對幾個函數(shù),就可以把search出來了

轉(zhuǎn)自:http://blog.chinaunix.net/uid-23842323-id-2656614.html
Reference:http://topic.csdn.net/u/20090316/11/ac003f13-d1da-49a5-b12f-90e57cbe5ac9.html

posted @ 2012-07-05 16:06 Daywei 閱讀(7336) | 評論 (0)編輯 收藏

任何時候都適用的20個C++技巧(轉(zhuǎn)載)

     摘要: 這些小技巧之所以特別,是因為這些信息通常吧不能在C++書籍或者網(wǎng)站上找到。比如說,成員指針,即使對于高級程序員也是比較棘手,和易于產(chǎn)生bugs的,是應(yīng)該盡量避免的問題之一。 <翻 by凌云健筆> What makes these tips special is that the information they provide usually cannot be found in ...  閱讀全文

posted @ 2012-06-29 17:29 Daywei 閱讀(464) | 評論 (0)編輯 收藏

《人月神話》經(jīng)典語錄

Good cooking takes time. If you are made to wait, it is to serve you better, and to please you.
美食的烹飪需要時間;片刻等待,更多美味,更多享受。

Adding manpower to a late software project makes it later.
向進(jìn)度落后的項目中增加人手,實惠使進(jìn)度更加落后。

對結(jié)構(gòu)師的建議:

 

  • 牢記是開發(fā)人員承擔(dān)創(chuàng)造性和發(fā)明性的實現(xiàn)責(zé)任,所以結(jié)構(gòu)師只能建議,而不能支配
  • 時刻準(zhǔn)備著為所指定的說明建議一種實現(xiàn)的方法,同樣準(zhǔn)備接受其他任何能達(dá)到目標(biāo)的方法
  • 對上述的建議保持低調(diào)和不公開
  • 準(zhǔn)備放棄堅持所做的改進(jìn)建議

一般開發(fā)人員會反對體系結(jié)構(gòu)上的修改建議。通常他是對的——當(dāng)正在實現(xiàn)產(chǎn)品時,某些次要特性的修改會造成意料不到的成本開銷。

Practice is the best of all instructors.
實踐是最好的老師。

Experence is  a dear teacher, but fools will learn at no other.
實踐是最好的老師,但智者還能從其他地方有所收獲。

There is nothing in this world constant but inconstancy.
不變只是愿望,變化才是永恒。

It is  commeon sense to take a method and try it. If it fails, admit it frankly and try another. But above all, try something.
普遍的做法是,選擇一種方法,試試看;如果失敗了,沒關(guān)系,再試試別的。不管怎么樣,重要的是先去嘗試。

What we do not understand we do not possess.
不了解,就無法真正擁有。

For brevity is very good, Where we are , or are not understood.
我們理解也好,不理解也好,描述都應(yīng)該簡短精煉。 

posted @ 2012-05-12 11:05 Daywei 閱讀(655) | 評論 (0)編輯 收藏

Recording DirectX and OpenGL Rendered Animations(翻譯)

記錄DirectX和OpenGL渲染的動畫
簡介
    當(dāng)我們創(chuàng)建游戲和仿真模擬時,有時我們有必要記錄渲染的內(nèi)容。在某些情況下渲染過于復(fù)雜和耗時,這是不可避免的。
     在DirectX中,庫函數(shù)D3DXSaveSurfaceToFile()保存表面為一張圖片文件。對OpenGL,我們用glReadPixels()來讀渲染的圖像像素然后手動的保存它們?yōu)橐粡垐D片文件。然而這些表面只是針對單幀記錄的,對記錄一段連續(xù)幀沒有簡單的方法存在。換句話說,沒有庫函數(shù)來記錄我們的完整存在渲染動畫效果。
    在這方面,本文提出了幾類,這有助于創(chuàng)造電影DirectX的方法和動畫。用類CDxToMovie和 CGLToMovie電影可以選擇性地或連續(xù)的從DirectX和OpenGL渲染幀來創(chuàng)建。一般來說,一個典型的電影創(chuàng)作過程涉及復(fù)雜的任務(wù),例如讀圖的內(nèi)容,選擇幀速率設(shè)置,編解碼器的設(shè)置,初始化媒體流,寫媒體流等(詳細(xì)討論關(guān)于如何創(chuàng)建位圖圖像序列的電影,請參考這篇文章Create Movie from HBitmap)。類CDxToMovie和CGLToMovie這里介紹的抽象出所有不必要的復(fù)雜性和易于使用的界面,提供簡單方法解釋如下
從DirectX渲染序列記錄一個電影
    類CDxToMovie可以記錄DirectX渲染序列成電影文件。該類用到DirectX 9.0接口例如LPDIRECT3DSURFACE9,因此你應(yīng)該用DirectX 9.0 SDK 或者其他的兼容的地方使用這個類 。
      開始從本文中的DirectX代碼拷貝文件DxToMovie.h,RenderTarget.h,AviFile.h和AviFile.cpp到你的工程目錄下然后添加他們到你的工程中,然后添加vfw.lib,一旦添加到你的工程中,你可以通過#include "DxToMovie.h"訪問。CDxToMovie構(gòu)造函數(shù)接受不同的參數(shù)如輸出電影文件名,電影幀的寬度和高度的要求,每像素比特數(shù)等…如下所示,
CDxToMovie(LPCTSTR lpszOutputMovieFileName = _T("Output.avi"),
                
int nFrameWidth = GetSystemMetrics(SM_CXSCREEN),  /*Movie Frame Width*/
                
int nFrameHeight = GetSystemMetrics(SM_CYSCREEN), /*Movie Frame Height*/
                
int nBitsPerPixel = 32,     /*Bits per Pixel*/
                DWORD dwCodec 
= mmioFOURCC('M','P','G','4'),  /*Video Codec for Compression*/
                DWORD dwFrameRate 
= 1)      /*Frame Rate (FPS) setting for the Movie*/
然而,應(yīng)該注意到的是,這是一個時間設(shè)置,后來在電影記錄時候不能改變 。每個CDxToMovie對應(yīng)一個不同的電影文件和再造一個CDxToMovie對象具有相同的輸出文件的名字不會追加以前的電影內(nèi)容,將覆蓋它。
CDxToMovie g_MovieRecorder("Output.Avi", 320, 240);
    一旦創(chuàng)建CDxToMovie對象,方法CDxToMovie::OnCreateDevice()在你的程序Direct3D設(shè)備創(chuàng)建的時候會被調(diào)用。類似的,CDxToMovie::OnLostDevice(),CDxToMovie::OnResetDevice()和CDxToMovie::OnDestroyDevice()也會在設(shè)備丟失銷毀的時候各自被調(diào)用。這些函數(shù)的原型顯示如下
class CDxToMovie
{
HRESULT OnCreateDevice(LPDIRECT3DDEVICE9 pd3dDevice);
HRESULT OnDestroyDevice(LPDIRECT3DDEVICE9 pd3dDevice);
HRESULT OnLostDevice();
HRESULT OnResetDevice(LPDIRECT3DDEVICE9 pd3dDevice,
const D3DSURFACE_DESC* pBackBufferSurfaceDesc);
}
;
函數(shù)OnCreateDevice()和OnDestroyDevice()接受一個單單參數(shù),指向你程序的Direct3D設(shè)備對象。OnLostDevice()沒有參數(shù),但是OnResetDevice()還要有一個指針指向你設(shè)備的后緩沖區(qū)表面 D3DSURFACE_DESC*。CDxToMovie對象提供一些信息在D3DSURFACE_DESC里 創(chuàng)造一個合適的offscreen渲染目標(biāo),可以用來記錄你的應(yīng)用程序的渲染。
真正記錄的功能是通過函數(shù)CDxToMovie::StartRecordingMovie()和CDxToMovie::PauseRecordingMovie().這兩個函數(shù)必須每一幀都要在IDirect3DDevice9::BeginScene()IDirect3DDevice9::EndScene()之間。如下所示
g_pd3dDevice->BeginScene();

    
// Capture the Rendering onto CDxToMovie's Render Target
    g_MovieRecorder.StartRecordingMovie(g_pd3dDevice);
        
// Render as usual..    
        g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,200),1,0);
        g_pd3dDevice
->SetStreamSource(0,g_pVB,0,sizeof(CUSTOMVERTEX));
        g_pd3dDevice
->SetFVF(D3DFVF_CUSTOMVERTEX);
        g_pd3dDevice
->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);
    g_MovieRecorder.PauseRecordingMovie(g_pd3dDevice);

    
// Copy the CDxToMovie's Render Target content back onto BackBuffer's Surface
    g_pd3dDevice->StretchRect(g_MovieRecorder.RecordingSurface(),
                              NULL,pBackSurface,
                              
0,D3DTEXF_NONE);

    g_pd3dDevice
->EndScene();
在上面的代碼段中, g_MovieRecorder.StartRecordingMovie(g_pd3dDevice)將所有隨后的渲染在CDxToMovie的內(nèi)部渲染目標(biāo)直到g_MovieRecorder.PauseRecordingMovie(g_pd3dDevice)被調(diào)用。所有的渲染工作在CDxToMovie的內(nèi)部渲染目標(biāo)上做,你的程序back surface將沒有任何有效的內(nèi)容顯示在你的應(yīng)用程序窗口。這不要緊,如果你的申請不只是創(chuàng)作這部電影沒有任何動畫直接呈現(xiàn)在屏幕上。然而,如果你記錄電影從一個互動游戲會話上,它會變壞屏幕不更新到最新的渲染的內(nèi)容(因為通過重新渲染目標(biāo),CDxToMovie內(nèi)容被偷了)。為了避免它,你可以選擇性地復(fù)制回CDxToMovie內(nèi)部的渲染目標(biāo)的內(nèi)容到你的應(yīng)用程序的back surface 使用方法IDirect3DDevice9:StretchRect(),其次是常見的g_pd3dDevice - > EndScene()和g_pd3dDevice - >Present()的要求會更新內(nèi)容的呈現(xiàn)在屏幕上背緩沖區(qū),使屏幕上更新。
如果你想避免一些幀被選擇性記錄在這部電影,只是不要叫g(shù)_MovieRecorder.StartRecordingMovie和g_MovieRecorder.PauseRecordingMovie()(相應(yīng)的 g_pd3dDevice - > StretchRect())對那些幀,并會直接渲染動畫在屏幕上(沒有被重定向到CDxToMovie內(nèi)部的渲染目標(biāo))。
演示代碼提供這個項目提供了一個簡單的應(yīng)用程序,使得DirectX屏幕上的一個三角形的動作,鼠標(biāo)移動窗戶上,這將simulatenously被渲染成電影文件和記錄(名叫output.avi)。跑演示的可執(zhí)行程序,確保你有MPG4編解碼器的計算機(jī)上安裝,目錄有寫權(quán)限去創(chuàng)建輸出電影文件。詳情請設(shè)置解碼器和平衡,請參考這篇文章Create Movie from HBitmap

Recording a Movie from OpenGL Rendered Sequence
先暫時不翻譯了,以后再翻。

注:第一次翻譯,水平比較差,還望各位看客見諒。
Reference: Recording DirectX and OpenGL Rendered Animations

posted @ 2012-04-28 15:08 Daywei 閱讀(1351) | 評論 (1)編輯 收藏

Linux下C/C++學(xué)習(xí)4——程序調(diào)試

gcc編譯的幾種錯誤信息及其解決方法
1.語法錯誤
   一般實在輸入代碼時括號不匹配或者使用了關(guān)鍵字。遇到語法錯誤,可以仙劍次錯誤提示中出現(xiàn)的第一個行號,如果該行沒有問題,就檢查該行所開始的語法模塊是否完整,然后修正該結(jié)構(gòu)。
2.頭文件錯誤
   如果編譯器出的錯誤提示說can not find include file ***.h,就說明是指定的包含文件有問題,系統(tǒng)在編譯過程中找不到指定的頭文件
3.類庫錯誤
   如果出現(xiàn)類似“ld:-lm:No such file or directory”的錯誤,可能是在默認(rèn)的目錄內(nèi)找不到相應(yīng)的類庫。這種問題的解決方法是在編譯時使用-I參數(shù)指定要使用的類庫所在的目錄。
4.未定義符號
   出現(xiàn)類似Undefined symbol 的提示,說明在編譯過程中發(fā)現(xiàn)了沒有被定義的符號變量

gdb簡介
gdb 程序名
gdb
這兩種方式均可進(jìn)入gdb的交互式調(diào)試界面。在交互模式中可以使用許多命令:
  • file;加載要調(diào)試的程序
  • kill;終止正在調(diào)試的程序
  • list;列出10行程序的源代碼
  • next;單步執(zhí)行程序
  • step;單步執(zhí)行程序,與next不同的是,其會進(jìn)入調(diào)用的函數(shù)內(nèi)部。而next只需要調(diào)用函數(shù)的結(jié)果。
  • run;運行加載的程序
  • quit;退出gdb
  • watch;監(jiān)視一個變量的值
  • break;在代碼里設(shè)置斷點,程序運行到斷點處時會停下來,然后用戶可用next或step單步執(zhí)行程序。但使用break的前提是程序在編譯時使用了g參數(shù)
  • make;不用退出gdb,重新編譯代碼,然后在gdb中運行
  • shell;可調(diào)用shell命令
  • bt;查看函數(shù)堆棧
  • c函數(shù);繼續(xù)運行
  • finish;退出函數(shù)
  • info;查看相關(guān)信息,如info break

posted @ 2012-04-04 14:26 Daywei 閱讀(509) | 評論 (0)編輯 收藏

linux下C/C++學(xué)習(xí)3——Makefile

假設(shè)我們有下面這樣的一個程序,源代碼如下:
/* main.c */
#include 
"mytool1.h"
#include 
"mytool2.h"
int main(int argc,char **argv)
{
    mytool1_print(
"hello");
    mytool2_print(
"hello");
}

/* mytool1.h */
#ifndef _MYTOOL_1_H
#define _MYTOOL_1_H
void mytool1_print(char *print_str);
#endif
/* mytool1.c */
#include 
"mytool1.h"
void mytool1_print(char *print_str)
{
    printf(
"This is mytool1 print %s\n",print_str);
}

/* mytool2.h */
#ifndef _MYTOOL_2_H
#define _MYTOOL_2_H
void mytool2_print(char *print_str);
#endif
/* mytool2.c */
#include 
"mytool2.h"
void mytool2_print(char *print_str)
{
    printf(
"This is mytool2 print %s\n",print_str);
}



當(dāng)然由于這個程序是很短的我們可以這樣來編譯
gcc -c main.c
gcc -c mytool1.c
gcc -c mytool2.c
gcc -o main main.o mytool1.o mytool2.o
這樣的話我們也可以產(chǎn)生main 程序,而且也不時很麻煩.但是如果我們考慮一下如果有一天我們修改了其中的一個文件(比如說mytool1.c)那么我們難道還要重新輸入上面的命令?也許你會說,這個很容易解決啊,我寫一個SHELL 腳本,讓她幫我去完成不就可以了.是的對于這個程序來說,是可以起到作用的,但是當(dāng)我們把事情想的更復(fù)雜一點,如果我們的程序有幾百個源程序的時候,難道也要編譯器重新一個一個的去編譯?
為此,聰明的程序員們想出了一個很好的工具來做這件事情,這就是make.我們只要執(zhí)行以下make,就可以把上面的問題解決掉.在我們執(zhí)行make 之前,我們要先編寫一個非常重要的文件.--Makefile.對于上面的那個程序來說,可能的一個Makefile 的文件是:
# 這是上面那個程序的Makefile 文件
main:main.o mytool1.o mytool2.o
gcc -o main main.o mytool1.o mytool2.o
main.o:main.c mytool1.h mytool2.h
gcc -c main.c
mytool1.o:mytool1.c mytool1.h
gcc -c mytool1.c
mytool2.o:mytool2.c mytool2.h
gcc -c mytool2.c
有了這個Makefile 文件,不過我們什么時候修改了源程序當(dāng)中的什么文件,我們只要執(zhí)行make 命令,我們的編譯器都只會去編譯和我們修改的文件有關(guān)的文件,其它的文件她連理
都不想去理的。
下面我們學(xué)習(xí)Makefile 是如何編寫的。
在Makefile 中也#開始的行都是注釋行.Makefile 中最重要的是描述文件的依賴關(guān)系的說明.一般的格式是:
target: components
TAB rule
第一行表示的是依賴關(guān)系.第二行是規(guī)則.
比如說我們上面的那個Makefile 文件的第二行
main:main.o mytool1.o mytool2.o
表示我們的目標(biāo)(target)main 的依賴對象(components)是main.o mytool1.o mytool2.o
當(dāng)倚賴的對象在目標(biāo)修改后修改的話,就要去執(zhí)行規(guī)則一行所指定的命令.就象我們的上面那個Makefile 第三行所說的一樣要執(zhí)行 gcc -o main main.o mytool1.o mytool2.o
注意規(guī)則一行中的TAB 表示那里是一個TAB 鍵
Makefile 有三個非常有用的變量.分別是$@,$^,$<代表的意義分別是:
$@--目標(biāo)文件,$^--所有的依賴文件,$<--第一個依賴文件.
如果我們使用上面三個變量,那么我們可以簡化我們的Makefile 文件為:
# 這是簡化后的Makefile
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
main.o:main.c mytool1.h mytool2.h
gcc -c $<
mytool1.o:mytool1.c mytool1.h
gcc -c $<
mytool2.o:mytool2.c mytool2.h
gcc -c $<
經(jīng)過簡化后我們的Makefile 是簡單了一點,不過人們有時候還想簡單一點.這里我們學(xué)習(xí)一個Makefile 的缺省規(guī)則
..c.o:
gcc -c $<
這個規(guī)則表示所有的 .o 文件都是依賴與相應(yīng)的.c 文件的.例如mytool.o 依賴于mytool.c
這樣Makefile 還可以變?yōu)椋?br /># 這是再一次簡化后的Makefile
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
..c.o:
gcc -c $<

Makefile的處理規(guī)則
   make命令在處理makefile時是遞歸處理的。同時,make在處理makefile時會檢測目標(biāo)文件與依賴文件的時間戳。這個特性降低了編譯文件時的時間開銷,因為其只增量編譯更新過的文件。還有一點要注意的是,makefile文件必須以makefile或Makefile為名。
對簡單Makefile文件的擴(kuò)充
   Makefile文件就像是一種小型的腳本語言,所以其也支持變量的定義,而靈活使用變量,可以增強Makefile的適應(yīng)性與靈活性。下面是一個使用變量的Makefile。

##########################################
NAME = myfirst
cc = gcc
ac = as
CFLAG = -Wall -o1 -g
#這是編譯源程序的編譯選項,具體含義可參見前面gcc參數(shù)介紹
${NAME} asfile : ${NAME}.o asfile.o
#使用變量時,應(yīng)該使用$提取符,然后用大括號將變量名括起來
 ${cc} ${CFLAG} ${NAME}.o -o ${NAME}
 ${cc} ${CFLAG} asfile.o -o asfile
${NAME}.o : ${NAME}.c
 ${cc} -c ${NAME}.c -o ${NAME}.o
asfile.o : ${NAME}.s
 ${ac} ${NAME}.s -o asfile.o
#由匯編代碼生成目標(biāo)文件
${NAME}.s : ${NAME}.c
 ${cc} -S ${NAME}.c -o ${NAME}.s
#生成匯編代碼的方法
other : ${NAME}.o
#other選項并未出現(xiàn)在最終目標(biāo)中,所以直接使用make命令不會執(zhí)行這一行。要執(zhí)行這一行,必須使用make other來執(zhí)行
 ${cc} ${CFLAG} ${NAME}.o -o other
#這里并未使用顯示規(guī)則來指定${NAME}.o的生成方式,因為對于make命令而言,如果在規(guī)則中發(fā)現(xiàn)name.o文件,其會自動尋找同名的c代碼(name.c),然后自動根據(jù)找到的代碼調(diào)用相應(yīng)的編譯器編譯生成name.o文件


好了,我們的Makefile 也差不多了,如果想知道更多的關(guān)于Makefile 規(guī)則可以查看相應(yīng)的文檔。

posted @ 2012-03-26 14:56 Daywei 閱讀(566) | 評論 (0)編輯 收藏

僅列出標(biāo)題
共4頁: 1 2 3 4 
<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

導(dǎo)航

統(tǒng)計

常用鏈接

留言簿

隨筆分類

隨筆檔案

文章檔案

牛人博客

搜索

積分與排名

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            激情成人中文字幕| 欧美日韩视频一区二区| 国产欧美一区二区三区在线看蜜臀| 亚洲老司机av| 亚洲黄色尤物视频| 欧美成人一区二区| 国产一区二区三区在线观看免费视频| 欧美在线首页| 久久不射2019中文字幕| 欧美激情在线狂野欧美精品| 日韩午夜视频在线观看| 亚洲三级色网| 国产亚洲综合性久久久影院| 蜜桃av久久久亚洲精品| 欧美激情无毛| 欧美在线影院在线视频| 可以看av的网站久久看| 亚洲男人第一av网站| 久久这里有精品15一区二区三区| 亚洲乱码日产精品bd| 欧美在线观看视频在线| 9色精品在线| 欧美日韩一区二区在线观看视频 | 欧美中文在线观看国产| 久久免费少妇高潮久久精品99| 久久久91精品| 一本色道久久88综合日韩精品 | 欧美大片免费观看| 久久久久网站| 国产精品一二| 99精品视频网| 一区二区三区回区在观看免费视频| 香蕉久久夜色精品| 香蕉久久精品日日躁夜夜躁| 国产精品日本精品| 一区二区三区导航| 小嫩嫩精品导航| 国产午夜亚洲精品不卡| 欧美一级黄色录像| 欧美大色视频| 日韩午夜在线| 欧美日韩在线视频一区| 亚洲欧洲午夜| 亚洲欧美日韩电影| 国产一区二区在线观看免费播放| 亚洲在线免费| 欧美freesex8一10精品| 亚洲精品一区在线观看| 国产精品日韩精品欧美在线| 久久免费视频网站| 亚洲伊人观看| 亚洲激情综合| 美女国产一区| 久久久久久久国产| 亚洲中午字幕| 最新亚洲电影| 国模一区二区三区| 欧美日韩一区二区在线视频| 欧美一区二区三区在线| 亚洲国产日韩欧美在线动漫| 一区二区毛片| 亚洲精品美女久久久久| 久久久久久穴| 午夜欧美不卡精品aaaaa| 亚洲国产岛国毛片在线| 国产一区二区三区的电影| 欧美精品福利| 欧美理论大片| 欧美高清不卡在线| 久久久精品性| 免费在线播放第一区高清av| 久久精品国产99精品国产亚洲性色| 亚洲美女av在线播放| 亚洲精品日本| 亚洲欧美国产精品va在线观看| 午夜激情综合网| 日韩视频在线免费| 日韩午夜剧场| 在线亚洲成人| 欧美与欧洲交xxxx免费观看| 亚洲影院色在线观看免费| 中文有码久久| 久久九九有精品国产23| 老**午夜毛片一区二区三区| 欧美日韩免费在线观看| 国产精品久久久久久模特| 国产综合色在线视频区| 伊人久久噜噜噜躁狠狠躁 | 亚洲国产婷婷香蕉久久久久久99 | 一区二区三区久久| 午夜日韩视频| 欧美大成色www永久网站婷| 欧美日韩一区二区三| 国产精一区二区三区| 狠狠色伊人亚洲综合成人| 夜夜嗨一区二区三区| 悠悠资源网亚洲青| 亚洲丝袜av一区| 亚洲二区三区四区| 久久精品中文字幕一区二区三区| 久久久噜噜噜久噜久久| 欧美午夜不卡视频| 尤物在线观看一区| 欧美在线视频一区二区三区| 亚洲激情午夜| 蜜桃久久av一区| 国产精品毛片一区二区三区 | 国产欧美日本一区二区三区| 一区二区三区视频免费在线观看| 亚洲狼人综合| 国产欧美另类| 女同性一区二区三区人了人一 | 蜜臀久久99精品久久久久久9| 国外成人网址| 欧美制服丝袜| 午夜精品一区二区三区四区| 欧美日韩不卡合集视频| 亚洲一区二区精品| 一区二区三区久久网| 国产精品欧美风情| 欧美在线观看一区| 免播放器亚洲一区| 亚洲最新合集| 性做久久久久久久免费看| 国产私拍一区| 欧美黄在线观看| 欧美精品情趣视频| 欧美亚洲网站| 国产精品久久久久久影视| 另类专区欧美制服同性| 国产精品国产三级国产a| 久久嫩草精品久久久久| 欧美人在线观看| 久久久精品五月天| 国产精品欧美日韩久久| 亚洲女性喷水在线观看一区| 一本大道av伊人久久综合| 91久久精品国产| 欧美色图首页| 亚洲美女黄网| 伊人久久综合97精品| 亚洲免费久久| 亚洲视频国产视频| 欧美日韩123| 最近中文字幕mv在线一区二区三区四区| 国产欧美日韩综合一区在线播放 | 午夜欧美大片免费观看 | 久久一本综合频道| 欧美巨乳波霸| 亚洲激情视频网站| 亚洲二区在线视频| 久久国产精品亚洲77777| 欧美一区视频| 国产亚洲欧洲一区高清在线观看| 夜夜嗨一区二区| 久久国产精品久久久久久久久久| 国产精品视频一区二区三区| 一本色道婷婷久久欧美| 亚洲欧美中文在线视频| 国内精品视频666| 欧美精品一区三区在线观看| 99视频一区| 久久深夜福利免费观看| 亚洲人成77777在线观看网| 欧美精品免费在线| 一本色道久久综合亚洲精品不卡| 午夜在线电影亚洲一区| 在线欧美视频| 国产精品入口尤物| 另类天堂av| 亚洲性感激情| 亚洲国产日韩精品| 久久爱另类一区二区小说| 在线不卡a资源高清| 国产精品jizz在线观看美国| 久久激情网站| 亚洲欧美变态国产另类| avtt综合网| 亚洲人成网站在线观看播放| 蜜桃av久久久亚洲精品| 久久久亚洲一区| 在线视频中文亚洲| 亚洲精品视频一区| 一区二区欧美在线观看| 亚洲福利视频网站| 美国成人毛片| 久久婷婷国产综合精品青草| 欧美亚洲一区二区在线| 亚洲香蕉成视频在线观看| 一本色道久久综合| 亚洲黄色av| 亚洲日本中文| 亚洲毛片播放| 亚洲男女毛片无遮挡| 午夜在线不卡| 欧美成人午夜激情视频| 久久精品91| 欧美激情精品久久久六区热门 | 久久一区二区三区国产精品| 美女日韩欧美|