您的位置:首页 > 编程语言 > C语言/C++

C/C++板块常见问题集

2011-10-08 14:28 211 查看
1:试图用cout输出全局类的析构.(可能是VC6的问题,如果你的编译器没出现问题,很好,别喷我)

引用自whillcoxdennis提问: http://topic.csdn.net/u/20090302/14/ca44881f-9664-4be8-9687-1dd098612d11.html
class CDemo

{

public:

CDemo(const char *str);

~CDemo();

private:

char name[20];

};

CDemo::CDemo(const char* str)

{

strcpy(name,str);

cout < <"cout:Construction called for " < <name < <endl;

}

CDemo::~CDemo()

{

cout < <"cout:Destruction called for " < <name < <endl;

printf(" printf:Destruction called for %s/n",name);

}

static CDemo GlobleObject("globeobject"); //这个是我们关注的,cout:Destruction called for globeobject并不会出现

void main()

{

CDemo LocalObjectInMain("localobjectinmain");

CDemo * pHeapObjectInMain=new CDemo("heapobjectinmain");

CDemo *pHeapObjectInFunc=new CDemo("heapobjectinfunc");

static CDemo StaticObject="staticobject";

}

这里globeobject的析构并没有被显示出来,为何呢?

加一句printf你就知道为何了.

因为cout析构在GlobleObject析构前.

2.关于VC6的问题:

有人说珍爱生命,远离VC6,确实有一定道理.

VC6对于friend,模板等几个bug,建议换VS测试.

如,重载操作符号,如果friend符号的定义在类体外会报错.

模板嵌套:

vector <vector <int>> bad; //error,VC6会把2维容器 >>认作输出符号.

vector <vector <int> > good;

此外VC6下编译模板,出现一堆警告的话,你在头文件前加

#pragma warning(disable:4786)

3.关于型参,实参不分,指针搞不清楚.具体不赘述了,看下面代码,把这3段都搞清楚,就可以了.不清楚可以参考林锐博士的 < <彻底搞定C指针>>

void Exchg1(int x, int y)

{

int tmp;

tmp=x;

x=y;

y=tmp;

printf("Exchg1:x=%d,y=%d/n",x,y);

}

void Exchg2(int &x, int &y)

{

int tmp;

tmp=x;

x=y;

y=tmp;

printf("Exchg2:x=%d,y=%d/n",x,y);

}

void Exchg3(int *x, int *y)

{

int tmp;

tmp=*x;

*x=*y;

*y=tmp;

printf("Exchg3:x=%d,y=%d/n",*x,*y);

}

void main()

{

int a=4,b=6;

Exchg1 (a,b) ;

printf("a=%d,b=%d/n",a,b);

Exchg2 (a,b);

printf("a=%d,b=%d/n",a,b);

Exchg3(&a,&b) ;

printf("a=%d,b=%d/n",a,b);

}

4.C风格字符串与标准库类型string不分

int i;

char * ch = "cchars"; //这是C风格字符串,结尾有'/0'

char mch[] = "mchars";

string str(ch); //string类的构造函数接收ch,并作转化

i = strcmp(ch,str); //error,有人喜欢把string类作参数输入到strcmp等C字符串函数里,肯定会出问题啊.

ch[0] = 'd'; //error,char *ch获取的内存是const,相当于const char *ch= "cchars";无法修改.

mch[0] = 'f'; //ok

5.关于指针和内存申请及越界

int *ptr1,*ptr2;

*ptr1=10; //error,ptr1未申请内存,未初始化,结果未定义,看似不容易出错,可很多人写链表就没有申请内存

ptr1 =(int *) malloc (sizeof(int));

*ptr1=10; //ok;

*ptr2 = 20; /error

ptr2=ptr1;

*ptr2 = 20; //ok,实际是修改ptr1和ptr2指向的同一块区域.

ptr2= new int[10];

ptr2[10]=5; //error,这样写你或与觉得很傻,但是实际上很多时候,你就不知不觉犯了这些错误.

free( ptr1 );

delete ptr2; //error,这样delete只会析构第一个元素

delete[] ptr2; //ok

关于指针,我还想说多一点.但是这个问题牵涉到函数作用域,所以我放在第9条.

6.关于字节对齐

struct st1

{

char p1; [0]

char p3; [1]

short p2; [2][3]

int p4; [4][5][6][7]

};

struct st2

{

char p1; [0]

short p2; [2][3] //占2字节,起始地址要是2个整数倍

char p3; [4]

int p4; [8][9][10][11] //4字节,起始地址是4的整数倍

};

为何sizeof(st1)==8;sizeof(st2)==12,2者不一样呢?看注释.

7.小于32字节数据的输出显示问题

8.关于IO流

scanf("a=%d,b=%d",&a,&b); //很多人喜欢这样写,然后输入3 4 就问,为何程序跑起来不对,这里应该输入3,4

scanf("a=%db=%d",&a,&b); // 这样是3 4

输入缓冲区很容易出现一些你不需要,或者容易出问题的字符,

建议用空就刷新一下.

fflush(stdin);

9.关于变量作用域:其实也算指针应用的问题

引用的是rwjbjn1问的一个帖子 http://topic.csdn.net/u/20090302/17/900b3797-3642-4569-a623-dc0f8ebd8401.html?seed=1325371970
//代码1

int A()

{

int test=10;

return test;

}

int main()

{

int a=A();

printf("%d/n",a);

return 0;

}

//代码2

char* A()

{

char p[]="hello world";

return p;

}

int main()

{

char *str=NULL;

str=A();

printf("%s",str);

}

代码1没问题,可是代码2有问题(可以有结果,但是结果不一定对,这是未定义的操作).为何自己分析,可以去看那个贴里.

注意

int A()

{

int test=10;

return test;

}

返回的是值, 的确调用完后test会释放, 但它的值被返回了



char* A()

{

char p[]="hello world";

return p;

}

返回的是指针, 确切讲是指针的值, 但因为"hello world"会释放, 所以返回的这个指针值没用了

(存放字符串的空间被释放掉了, 这个指针值还有什么用?)

10.数据溢出

数据溢出,道理很简单,可是代码一长.有人不知不觉就犯错误了.

int main()

{

int b= 1294754725065626467; //32位机的int只支持32位(2^32-1)的有效计数

char a=199; //8bit的char数据只支持0到127的有效计数

cout < < a < <endl;

cout < < b < <endl;

printf("%c",a);

printf("%c/n",a);

}

不要试图解释结果,溢出了,就没什么好解释的了.什么诡异事都有.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: