天天看点

一些编程或者算法小技巧或小知识点

持续更新中…

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; // 递减算法

           

继续阅读