文章目錄

写程序时经常会遇见些莫名其妙的错误,往往花了大把时间找了很久的bug,最终发现这些都是很小很小的问题,所以把这些可能问题记下来备忘。

1.指针的加减操作
指针的加减操作都是其所指的内容相关的,好比char*+1等于实际地址+1,但int*+1等于实际地址+4,不能像当然的认为p+n就等于地址+n。

1
2
3
4
5
6
7
8
struct sdata  
{
int length;
char* pdata;
};
sdata* pmem = (sdata*)malloc(1024);
pmem->pdata = (char*)(pmem + sizeof(sdata));
pmem->length = 0;

程序中我本意是给申请的内存加个头,便于管理,pdata指向可用内存地址,length记录内存所用长度,但是没有达到预期的效果,而且在运用中造成了严重的宕机。究其原因就是因为pmem->pdata = (char)(pmem + sizeof(sdata));这句pmem做加法的时候所增长的长度远远大于预期,它是根据pmem所指的类型的长度增长的,即增长了sizeof(sdata)sizeof(sdata)。如果想要地址实际增加sizeof(sdata),应该这样

1
pmem->pdata = (char*)((char*)pmem + sizeof(sdata));

切记不要随便对指针做加减操作!

2.整型提升相关

在一个表达式中,凡是可以使用整型的地方都可以使用带符号或无符号的字符、短整型或整型位字段,还可以使用枚举类型的对象。如果原始类型的所有值都可以用int类型表示,则其值将被转换为int类型;否则将被转换为unsigned int类型,这一过程称为整型提升。

1
2
3
4
5
unsigned char a = 0xF8;  
unsigned char b = (~a)>>4;
unsigned char c = ~a;
c = c>>4;
unsigned char d = ((unsigned char)~a)>>4;

上面结果a=248,b=240,c=0,d=0,其中b的值不是所期望的,因为~a被整型提升到了int,然后右移4位,最后被转为unsigned char。

1
int i = -1;if(i < sizeof(i)) return true;else return false;

比较时i会被转换为unsigned int即0xffffffff,所以结果返回false。

3.static

static存储在静态数据区,经常在函数中使用静态局部变量记录一些数据,好处就是函数外不可见,而且其值一直是保存着的以便下次进入函数再次访问。但是要注意在多线程环境中这些static变量也是共享的,即可能同时被多个线程访问并修改,切记切记,因为这个原因悲剧的调试程序调了2天……

4.set map

在set map中key如果是自定义结构体时,更改key中某项的值并不会引起set和map的重新排序,如果想达到排序效果则需要先删除该key,然后插入新key。

5.template

类模板成员函数的声明和定义都要放在.h里面,不然会有无法解析的外部符号错误。

6.std::string

string并不一定是以’\0’结束的,这要看编译器的实现方式,所以可能cout<<string与cout<<string.c_str()是不同的,在程序中要注意你是需要string的内容还是string.c_str的内容。(C++11标准规定string以’\0’结束,但尚未统一)。

7.const string&与const char*

作为函数参数const string&是兼容const char*的,所以一般情况下使用const string&就好了(虽然相比效率可能低那么一点),但是有时候也不好使。

1
2
3
4
5
class A{
public:
A(const string&);
};
void fun(const A& a){}

此时调用fun(“xx”);失败,如果添加构造函数A(const char*);则会调用成功。或者调用fun(A(“xx”));

8.类成员初始化

用初始化列表进行类成员初始化的时候,初始化列表中成员变量的顺序要和类定义里面成员变量的顺序保持一致,否则将有警告产生。

文章目錄