日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C/C++编程心得

發(fā)布時(shí)間:2023/12/20 c/c++ 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C/C++编程心得 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://antkillerfarm.github.io/

參考資料

http://www.cplusplus.com/

這個(gè)網(wǎng)站可以查到C++的標(biāo)準(zhǔn)庫(kù)的用法。

頭文件被多個(gè)源文件引用

在頭文件中定義字符串時(shí),如果該頭文件會(huì)被多個(gè)源文件引用的話,字符串必須被定義為const,否則會(huì)有重定義錯(cuò)。當(dāng)然最好在頭文件中只放聲明,不要放定義。

使用諸如

#ifndef _COMMON_STRING_ #define _COMMON_STRING_ ... ... ... #endif

解決不了這個(gè)問題。因?yàn)檫@段代碼解決的是同一個(gè)源文件重復(fù)包含某個(gè)頭文件的問題。而這里的問題是不同的源文件包含同一頭文件時(shí),產(chǎn)生的重復(fù)定義的問題。const關(guān)鍵字保證了同一標(biāo)識(shí)符只會(huì)定義一次。

指針數(shù)組與數(shù)組指針

int (*p)[10] 先是 *p起作用 ,聲明一個(gè)指針(p肯定是指針了),然后是[10](數(shù)組說(shuō)明),則p是指向10個(gè)整形元素組成的數(shù)組的指針?!獢?shù)組指針。

若是int *p[10] 則首先是[ ]起用,它是一個(gè)數(shù)組了。然后是*,所以這個(gè)數(shù)組元素是指針型的。——指針數(shù)組。

引申一下

int a[10];printf("%x\n",&a);printf("%x\n",a);

可以看到&a和a的值是相等的,但含義不同。a相當(dāng)于int *p,而&a相當(dāng)于int (*p)[10]。

類似的

int (*p[])(int)函數(shù)指針數(shù)組。

int (*p())[]返回?cái)?shù)組指針的函數(shù)。

int *p()[]字面上可以解釋為返回指針數(shù)組的函數(shù),不過函數(shù)是不能返回?cái)?shù)組的。

int *(*a())()這是一個(gè)函數(shù),它沒有參數(shù),它的返回值是一個(gè)函數(shù)指針,這個(gè)指針指向的函數(shù),也沒有參數(shù),且返回值是int型的指針。

嵌入式程序員應(yīng)知道的幾個(gè)基本問題

http://linux.chinaitlab.com/c/713810.html

深入理解C++中的mutable關(guān)鍵字

http://dev.yesky.com/393/3007393.shtml

UNREFERENCED_PARAMETER的作用

http://blog.csdn.net/apunix/archive/2008/01/14/2043945.aspx

sizeof進(jìn)行結(jié)構(gòu)體大小的判斷

http://blog.csdn.net/van150/archive/2005/12/05/544454.aspx

VC的默認(rèn)規(guī)則基本如上所示,gcc的默認(rèn)規(guī)則就是4字節(jié)對(duì)齊。

可以比較一下

struct s {char a;double b;int c; }

struct s {char a;int b;double c; }

在各個(gè)平臺(tái)上的sizeof值。

附帶說(shuō)一下如果看到以下的代碼片段,也就不要覺得驚奇了。

typedef enum _XXX {XXX_0 = 0,XXX_1 = 1,XXX_FORCE_DWORD = 0x7FFFFFFF/* 編譯器對(duì)齊 */ }XXX;

字節(jié)對(duì)齊的設(shè)定

1)編譯器選項(xiàng)指定

VC:/Zp

gcc:-fpack-struct

2)代碼指定

VC和gcc都可以用#pragma pack(4)

gcc還可以用__attribute__((packed))

Java中創(chuàng)建對(duì)象的時(shí)候代碼執(zhí)行順序(這個(gè)問題C++應(yīng)該也存在)

http://jacob777.blog.sohu.com/106426297.html

宏展開函數(shù)的小技巧

有的時(shí)候,會(huì)使用宏展開的方式定義“偽”函數(shù)。

這些“偽”函數(shù)有以下特征:

  • 不是真正的函數(shù),而是接受參數(shù)的宏。

  • 形式上與普通函數(shù)相同。

  • 為了實(shí)現(xiàn)這個(gè)功能,教科書上給出的做法是這樣的:

    #define st(x) do { x } while (0) #define HAL_DMA_SET_SOURCE( pDesc, src ) \st( \pDesc->srcAddrH = (uint8)((uint16)(src) >> 8); \pDesc->srcAddrL = (uint8)( (uint16)(src) & 0xFF ); \)

    但是do { x } while (0)在有些編譯器上會(huì)報(bào)warning。最近看Ti的代碼的時(shí)候,看到了一種更好的辦法:

    #define st(x) do { x } while (__LINE__ == -1)

    C++ 11的新特性

    我是在2003年以后學(xué)習(xí)C++的,后來(lái)直到2009年以前,C++都是我的主要工作語(yǔ)言。但由于本人先學(xué)的C語(yǔ)言,所以編程的思想一直是函數(shù)式的。完成一項(xiàng)任務(wù),無(wú)論用C、C++、Java、C#,還是Matlab、Python,風(fēng)格都是差不多的。這也是后來(lái)我對(duì)GTK情有獨(dú)鐘的一個(gè)重要的原因。

    總的來(lái)說(shuō),我對(duì)C++用的多,但理解的卻不深。只對(duì)單繼承、成員函數(shù)的封裝、訪問之類的概念有一定的認(rèn)識(shí)和使用。多重繼承、模板會(huì)看不會(huì)寫。更不必提C++ 03和C++ 11的新特性了。最近因?yàn)檠芯緾ocos2d-x,而接觸到這些新特性,頗有些感覺到自己已經(jīng)是老古董了.

    不過好在Java語(yǔ)言用的還可以,大部分的C++新特性,學(xué)起來(lái)倒也難不倒我。

    1.auto關(guān)鍵字

    C++11中引入的auto主要有兩種用途:自動(dòng)類型推斷和返回值占位。auto在C++98中,標(biāo)識(shí)臨時(shí)變量的語(yǔ)義,由于使用極少且多余,在C++11中已被刪除。前后兩個(gè)標(biāo)準(zhǔn)的auto,完全是兩個(gè)概念,這點(diǎn)尤其需要注意。

    http://blog.csdn.net/huang_xw/article/details/8760403

    2.引入nullprt

    http://blog.csdn.net/huang_xw/article/details/8764346

    3.仿函數(shù)、lambda表達(dá)式和閉包

    http://www.cnblogs.com/npbool/p/3434757.html

    4.C++、Java和C#的lambda表達(dá)式的格式

    C++

    auto func = [=](int x, int y)->int {return x * y;};

    Java

    Runnable r1 = (int x, int y) -> { return x * y; }

    C#

    Func<int, int, int> towParams = (x, y) => x * y

    添加廢棄提示

    有些類庫(kù)出于兼容性的考慮,仍然保留了對(duì)舊函數(shù)的支持。但是繼續(xù)使用這些函數(shù),顯然不是作者的初衷。因此,有必要在編譯時(shí),給出廢棄的提示。

    近日瀏覽cocos2d-x v3的代碼,發(fā)現(xiàn)可以這樣做:

    宏定義:

    #if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) #define CC_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) #elif _MSC_VER >= 1400 //vs 2005 or higher #define CC_DEPRECATED_ATTRIBUTE __declspec(deprecated) #else #define CC_DEPRECATED_ATTRIBUTE #endif

    宏使用:

    CC_DEPRECATED_ATTRIBUTE static TextureCache * getInstance();

    關(guān)于引用的一個(gè)常見錯(cuò)誤

    class Base {public:void something(Base& b){} };int main() {Base b;b.something(Base());return 0; }

    上面的代碼在編譯時(shí),會(huì)出現(xiàn)如下錯(cuò)誤信息:

    abc.cpp:12:20: error: no matching function for call toBase::something(Base)abc.cpp:12:20: note: candidate is: abc.cpp:6:7: note: void Base::something(Base&) abc.cpp:6:7: note: no known conversion for argument 1 fromBasetoBase&’

    這是由于Base()生成的是臨時(shí)變量,將之賦值給一個(gè)non-const的引用是不行的。

    解決方法是

    void something(const Base& b){}

    可以參看下文:

    http://stackoverflow.com/questions/20247525/about-c-conversion-no-known-conversion-for-argument-1-from-some-class-to

    常用libc實(shí)現(xiàn)

    libc是C語(yǔ)言標(biāo)準(zhǔn)庫(kù)的簡(jiǎn)稱,它有多種實(shí)現(xiàn)。除了最常用的gcc自帶的glibc之外,還有musl、uClibc、dietlibc等。

    http://www.etalabs.net/compare_libcs.html

    這個(gè)網(wǎng)址是以上4種libc實(shí)現(xiàn)的比較結(jié)果。從結(jié)果來(lái)看,musl比較有投資價(jià)值。實(shí)際上,最近(2015.5)的OpenWrt項(xiàng)目就已經(jīng)將libc由uClibc改為musl。我也是因?yàn)檫@個(gè)原因,才知道m(xù)usl的。

    當(dāng)然這個(gè)表并不完整,其他的libc可以參見:

    https://en.wikipedia.org/wiki/C_standard_library

    數(shù)組定義時(shí)的賦值方法

    struct mtd_partition {const char *name; /* identifier string */uint64_t size; /* partition size */uint64_t offset; /* offset within the master MTD space */ };static struct mtd_partition parts[] = {{name: "boot", offset: 0, size:0x500000,},{name: "setting", offset: 0x500000, size:0x300000,},{name: "linux", offset: 0x800000, size:0x500000,}, {name: "config", offset: 0xd00000, size:0x100000,}, {name: "rootfs", offset: 0xe00000, size:0x3200000,},{name: "app", offset: 0x4e00000, size:0x800000,},};static struct resource pxa27x_resource_ohci[] = {[0] = {.start = 0x4C000000,.end = 0x4C00ff6f,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_USBH1,.end = IRQ_USBH1,.flags = IORESOURCE_IRQ,}, };

    這些方法雖然不知道是C的那個(gè)標(biāo)準(zhǔn)引入的,但是見到有代碼這樣用。

    switch…case

    switch (reg) {case TAS5086_CLOCK_CONTROL ... TAS5086_BKNDERR:return 1;case TAS5086_INPUT_MUX:case TAS5086_PWM_OUTPUT_MUX:return 4; }

    可以用上面的辦法,少寫一些case語(yǔ)句。

    動(dòng)態(tài)鏈接

    這兩天實(shí)踐了一下怎樣在linux下創(chuàng)建動(dòng)態(tài)鏈接。感覺網(wǎng)上的資料雖然翔實(shí),但仍然有疏漏之處。

    1)g++和gcc的區(qū)別

    本來(lái)只想給鏈接的,以顯示這不是我的原創(chuàng)。但是現(xiàn)在的鏈接失效的也太快了。。。囧

    只好拿華麗的分隔符來(lái)表示引用的內(nèi)容。


    誤區(qū)一:gcc只能編譯c代碼,g++只能編譯c++代碼

    兩者都可以,但是請(qǐng)注意:

    1.后綴為.c的,gcc把它當(dāng)作是C程序,而g++當(dāng)作是c++程序;后綴為.cpp的,兩者都會(huì)認(rèn)為是c++程序,注意,雖然c++是c的超集,但是兩者對(duì)語(yǔ)法的要求是有區(qū)別的。C++的語(yǔ)法規(guī)則更加嚴(yán)謹(jǐn)一些。

    2.編譯階段,g++會(huì)調(diào)用gcc,對(duì)于c++代碼,兩者是等價(jià)的,但是因?yàn)間cc命令不能自動(dòng)和C++程序使用的庫(kù)聯(lián)接,所以通常用g++來(lái)完成鏈接,為了統(tǒng)一起見,干脆編譯/鏈接統(tǒng)統(tǒng)用g++了,這就給人一種錯(cuò)覺,好像cpp程序只能用g++似的。

    誤區(qū)二:gcc不會(huì)定義__cplusplus宏,而g++會(huì)

    實(shí)際上,這個(gè)宏只是標(biāo)志著編譯器將會(huì)把代碼按C還是C++語(yǔ)法來(lái)解釋,如上所述,如果后綴為.c,并且采用gcc編譯器,則該宏就是未定義的,否則,就是已定義。

    誤區(qū)三:編譯只能用gcc,鏈接只能用g++

    嚴(yán)格來(lái)說(shuō),這句話不算錯(cuò)誤,但是它混淆了概念,應(yīng)該這樣說(shuō):編譯可以用gcc/g++,而鏈接可以用g++或者gcc -lstdc++。因?yàn)間cc命令不能自動(dòng)和C++程序使用的庫(kù)聯(lián)接,所以通常使用g++來(lái)完成聯(lián)接。但在編譯階段,g++會(huì)自動(dòng)調(diào)用gcc,二者等價(jià)。


    因此,某些時(shí)候編不過去,可以試試換換cc的值。

    2)gcc4.1.1下似乎對(duì)類型檢查嚴(yán)了一些,dlsym返回的void*類型不能轉(zhuǎn)換為相應(yīng)的函數(shù)指針類型,需要強(qiáng)制轉(zhuǎn)換。某些網(wǎng)上的例子在這里編不過去。

    3)顯式調(diào)用時(shí),要注意動(dòng)態(tài)庫(kù)函數(shù)的聲明,可能要加extern "C"才能正常執(zhí)行。(顯式調(diào)用是運(yùn)行時(shí)加載,所以編譯能過,執(zhí)行卻不對(duì)了。)可以用nm命令看看鏈接庫(kù)的符號(hào)表,以確定問題所在。

    4)鏈接的時(shí)候需要注意文件的順序。

    比如下面的例子:

    https://github.com/antkillerfarm/antkillerfarm_crazy/tree/master/helloworld/linux_so

    gcc -o main_link main_link.c -L. -lhello

    這條命令中的main_link.c如果放到-lhello之后就會(huì)出問題。也考慮使用--start-group和--end-group之類的鏈接選項(xiàng)解決鏈接順序問題。

    cout格式化輸出

    cout<<hex<<i<<endl; //輸出十六進(jìn)制數(shù) cout<<oct<<i<<endl; //輸出八進(jìn)制數(shù) cout<<dec<<i<<endl; //輸出十進(jìn)制數(shù)

    strtok

    strtok函數(shù)多用于分割字符串,但它會(huì)改變被分割字符串的值。因此,如果該字符串以后還有用的話,需要首先復(fù)制該字符串,然后對(duì)復(fù)制的字符串執(zhí)行strtok函數(shù)。

    K&R風(fēng)格

    在C語(yǔ)言的函數(shù)定義上,我們通常用的函數(shù)定義方式為ANSI C的函數(shù)定義方式。但是在C語(yǔ)言之父創(chuàng)立C語(yǔ)言之時(shí),函數(shù)的定義形式并非現(xiàn)在我們所見到的形式。

    這種風(fēng)格被稱為K&R風(fēng)格,多見于一些歷史悠久的項(xiàng)目或者老的書籍中。出于兼容性考慮,現(xiàn)代的C編譯器仍然支持K&R風(fēng)格。

    詳見:

    http://blog.chinaunix.net/uid-7426920-id-2627743.html

    總結(jié)

    以上是生活随笔為你收集整理的C/C++编程心得的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。