1.获取类名:
void PrintClassName(void *p)
{
type_info *** vtable = (type_info ***)(*(int*)p);
type_info ** v1 = vtable[-1];
type_info * v = v1[3];
printf("printName: %s
", v->name());
}
前提:该类必须有virtual 成员
例如:
class class1
{
char a;
double b;
public:
virtual ~class1(){}
};
2. 日志打印:对printf的一个封装,增加些prefix。在头文件中定义(包含的有<time.h><stdarg.h>)
#define PRINT(...) Print(__FILE__, __LINE__, __VA_ARGS__)
inline void Print(const char * fileName, int lineNum, const char * fmt, ...)
{
std::string full_name = fileName;
int n = full_name.find_last_of('\');
full_name = full_name.substr(n+1, full_name.length());
time_t now = time(NULL);
char timeStr[128];
strftime(timeStr, sizeof(timeStr), "%Y-%m-%d_%H-%M-%S", localtime(&now));
printf("#Debug# %s [%s:%d] ", timeStr, full_name.c_str(), lineNum);
char tmp[1024];
va_list args;
va_start(args, fmt);
int printed = vsnprintf(tmp, sizeof(tmp)-1, fmt, args);
va_end(args);
tmp[sizeof(tmp)-1] = ' ';
//puts(tmp);
printf("%s", tmp);
/* from glic printf.c
va_list arg;
va_start(arg, fmt);
int done = vfprintf(stdout, fmt, arg);
va_end(arg);
*/
}
调用:包含定义头文件调用: PRINT("n = %d, s = %s ", 990, "nolang");
3. 测试代码段执行时间:
clock_t clock_begin = clock();
for (int i = 0; i < MAXLENGTH; ++i) .....
clock_t clock_end = clock();
std::cout<<"execute: "<<clock_end-clock_begin<<" times"<<std::endl;
4. 应用程序无法正常启动0xc00007b:在搭建luacpp时,遇到过一次,其实是没有lua.dll文件。网上一堆说是dx9的缺失。
5. 定义一个空的数据类型,里面没有任何成员变量和成员函数,求sizeof
答案:1,为什么不是0?空类型的实例中不包含任何信息,本来求sizeof应该是0,但声明该类型的实例时,它必须在内存中占有一定的空间,否则无法使用这些实例(也就不能求sizeof了),至于占用多少内存由编译器决定,Visual Studio中占用1字节的空间。
扩展1:如果在该类型中添加一个构造函数和析构函数,再求sizeof
答案:1。调用构造函数和析构函数只需要知道函数的地址即可,而这些地址只与类型相关与类型的实例无关,编译器不会因为这两个函数而在实例内添加任何额外的信息。
扩展2:把析构函数标记为虚函数呢?
答案:C++的编译器一旦发现有虚函数会生成虚函数表,并在类的实例中添加一个指向虚函数表的指针,32位机器上占4字节,如果是64位则为8。
6. Tomohiko Sakamoto提供的优雅的代码由一个日期获取星期几
int dayofweek(int y, int m, int d) /* 0 = Sunday */
{
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= m < 3;
return (y + y/4 - y/100 + y/400 + t[m - 1] + d) % 7;
}
7.
在c++中:
(1)register 关键字无法在全局中定义变量,否则会被提示为不正确的存储类。
(2)register 关键字在局部作用域中声明时,可以用 & 操作符取地址,一旦使用了取地址操作符,被定义的变量会强制存放在内存中。
在c中:
(1)register 关键字可以在全局中定义变量,当对其变量使用 & 操作符时,只是警告“有坏的存储类”。
(2)register 关键字可以在局部作用域中声明,但这样就无法对其使用 & 操作符。否则编译不通过。
建议不要用register关键字定义全局变量,因为全局变量的生命周期是从执行程序开始,一直到程序结束才会终止,
而register变量可能会存放在cpu的寄存器中,如果在程序的整个生命周期内都占用着寄存器的话,这是个相当不好的举措。
C++并不是完全兼容C语言的,sizeof('a')等于几的问题也是一例
8. std::cout的格式化模式恢复
std::ostream::fmtflags old = std::cout.flags();
std::cout.flags(old);
9.查看16进制文件数据。一行16个字节,高位在右
AA 05 00 00 这4个字节读取为 000005AA即5AA
32 00 00 00 AA 05 00 00 这个8个字节5AA00000032
10.成员函数模板特化:一定要特化在相同namespace里。甚至不需要声明。模板函数不能偏特化,这种需偏特化的那个函数用函数重载解决。
namespace pp {
struct Tfun {
template<typename T> void fund(char a, T b);
//template<> void fund<int>(char a, int b);
};
template<typename T> void Tfun::fund(char a, T b) {
COUT("template pp");
}
template<> void Tfun::fund<int>(char a, int b) {
COUT("template p1");
}
}