天天看點

一些程式設計或者算法小技巧或小知識點

持續更新中…

1. 字元大小寫轉換

大寫轉小寫:
char LowChar = (UpperChar | 0X20);

小寫轉大寫:
char UpperChar = (LowChar & -33);
           

2. 兩個整數之和的一半

(x + y) / 2 = (x & y) + ((x ^ y) >> 1)
           

其中, x x x和 y y y都是整數。

此外,如果是計算一段距離的中點的話,不建議使用和的一半:

int mid = (start + end) / 2; // 這種方法不好,因為有可能x+y的值超過範圍了,導緻整數溢出

int mid = start + (end - start) / 2; // 這種方法就比較好,不會發生整數的溢出
           

3. 多線程間資料共享

如果多個線程共享同一個資料,且至少有一個線程是通過非直接方式來擷取此資料的值(比如通過指針指向此資料的位址),則這個資料應該定義成volatile的,因為編譯器有可能經過優化後,會将資料緩存到寄存器中,導緻線程可能會擷取到不正确的資料。

4. Windows下使用CreateThread()和_beginthreadex()的差別

根據《Win32多線程程式設計》中的介紹,當建立的子程式中包含某些C runtime 函數時,不應該使用

CreateThread()

如果主線程以外的任意建立的線程中包含以下操作,則應該使用多線程版本的C runtime library,并使用

_beginthreadex()

_endthreadex()

  • 在C程式中使用

    malloc()

    free()

    ,或者在C++程式中使用

    new()

    delete()

  • 調用

    stdio.h

    io.h

    中聲明的任何函數,包括

    fopen()

    open()

    getchar()

    write()

    printf()

    等等。所有這些函數都用到共享的資料結構以及

    errno

    。對于格式化操作,如果不想使用C runtime library的函數,你可以使用

    wsprintf()

    來替代

    printf()

    (wsprintf()是Win核心自己實作的,不依賴于C runtime library,其與printf()大同小異,唯一差別是在浮點數的處理上不同);
  • 使用浮點變量或者浮點運算函數;
  • 調用任何一個使用了靜态緩沖區的runtime函數,如

    asctime()

    strtok

    rand()

如果建立的線程裡面沒有以上列出來的事項,則可以用單線程版本的runtime library和CreateThread()。

此外,如果要在MFC程式中産生一個線程,而該線程将調用MFC函數或使用MFC的任何資料,那麼必須使用

AfxBeginThread()

CWinThread::CreateThread()

來産生線程。

5. 使用共享記憶體來實作程序間通信注意事項

程序間通信的一種方式是使用共享記憶體,不管是使用

SendMessage()

通過

COPYDATASTRUCT

結構體來實作還是通過建立

FileMap(檔案映射)

的方式來實作,注意,被共享的變量中一定不能含有指針,隻能是數值。程序間共享記憶體隻能共享數值,而不能共享位址。比如,如果想把A程序中string對象共享給B程序,則因為string中的真正的字元串是存儲在A程序的heap中的,是通過指針來引用的。然而不同程序中,記憶體環境不一樣,是以位址

0xabcde

在A程序中可能指到string中的字元串内容,但是此位址在B程序中所指的内容根本與string中的字元串沒半毛錢關系,兩個程序的位址是獨立的。

注意,如果一個類中含有虛函數,則此類的對象也不能被共享,因為此類中含有虛函數表,也是指針。

6. C++ 中函數限定符出現在聲明和定義處的整理

1. noexcept:
	必須出現在函數的所有聲明和定義處;
	
2. inline:
	隻需要出現在函數定義處,且此函數隻能定義在頭檔案中,不應該定義在源檔案中;

3. explicit:
	隻能出現在成員函數聲明處;

4. static: 
	隻能出現在函數聲明處;

5. 函數預設實參:
	隻能出現在函數聲明處;

6. final:
	隻能出現在函數聲明處;

7. override:
	隻能出現在函數聲明處;
	
           

7. n 個bit位能表示帶符号整數的範圍

其範圍為 [-2n-1, 2n-1 - 1]。比如4個bit位能表示的整數範圍為 [-8, 7]。

8. 判斷某個數為奇數或者偶數的快速方法

由于偶數的比特位的最後一位肯定是0,而奇數的最後一位肯定是1,是以使用位運算的方式最快:

int x = 9;
if ((x & 1u ) == 0)
	std::cout << "偶數\n";
else
	std::cout << "奇數\n";
	
           

此外,如果将一個整數除以2的倍數或乘以2的倍數,則可以直接用移位的方式。

9. -fno-elide-constructors作用:

用于G++編譯器,用于取消編譯器對構造函數的優化,詳情百度。

10. 在區間[i, j]之間遞增或遞減(間隔為t),且無限循環:

int t = 5; // 遞增或遞減間隔
int i = 1, j = 21; // 區間為[1, 21],閉區間

int x = 0; // 記錄的值,開始為0,則從i開始進行遞增或遞減

while (true)
	x = (x - i + t) % (j - i + t) + i; // 遞增算法

while (true)
	x = (x - 2 * i + j) % (j - i + t) + i; // 遞減算法

           

繼續閱讀