C语言程序设计初学者常犯错误集锦

C编译的程序对语法检查并不象其它高级语言那么严格,这就给编程人员留下“灵活的余地”,但还是由于这个灵活给程序的调试带来了许多不便,尤其对初学C语言的人来说,经常会出一些连自己都不知道错在哪里的错误。看着有错的程序,不知该如何改起,本人通过对C的学习,积累了一些C编程时常犯的错误,写给各位学员以供参考。C语言C++学习交流群 496926338

1)运行下图中的4, 1, 100, 4。32位机器上,任意指针都占*pString1是字符串pString2是一个数组,100个字符,因此大小是SizeOf中,虽然传入的参数是一个字符数组,当数组作为函数的参数进行传递时,数组就自动退化为同类型的指针。

(2)

#include

using namespace std;

class A

{

public:

A()

{std::cout << "A is created." << std::endl;}

~A()

{std::cout << "A is deleted." << std::endl;}

};

class B : public A

{

public:

B()

{std::cout << "B is created." << std::endl;}

~B()

{std::cout << "B is deleted." << std::endl;}

};

int main(int argc, char* argv[])

{

A* pA = new B();

delete pA;

return 0;

}

答案:输出三行,分别是:new创建B的构造函数。在调用B的构造函数的时候,会先调用A的构造函数。因此先输出delete语句时,会调用析构函数。由于A的指针,同时基类virtual,因此只有B的析构函数。

由于B的实例的指针,但在析构的时候只调用了基类B的析构函数。这就是一个问题。如果在类型B中创建了一些资源,比如文件句柄、内存等,在这种情况下都得不到释放,从而导致资源泄漏。

(3)

#include

#include

using namespace std;

struct Point3D

{

int x;

int y;

int z;

};

int main(int argc, char* argv[])

{

Point3D* pPoint = NULL;

int offset = (int)(&(pPoint->z));

printf("%dn", offset);

return 0;

}

输出8。由于在pPoint->z的前面加上了取地址符号,运行到此时的时候,会在pPoint的指针地址上加z在类型Point3D中的偏移量8。由于pPoint的地址是0,因此最终offset的值是8。

&(pPoint->z)的语意是求pPoint中变量z的地址(pPoint的地址0加z的偏移量8),并不需要访问pPoint指向的内存。只要不访问非法的内存,程序就不会出错。

(4)

class A

{

private:

int m_value;

public:

A(int value)

{

m_value = value;

}

void Print1()

{

printf("hello world");

}

void Print2()

{

printf("%d", m_value);

}

};

int main(int argc, char* argv[])

{

A* pA = NULL;

pA->Print1();

pA->Print2();

return 0;

}

C语言C++学习交流群 496926338

分析:答案是Print1调用正常,打印出hello world,但运行至Print2时,程序崩溃。调用Print1时,并不需要pA的地址,因为Print1的函数地址是固定的。编译器会给Print1传入一个this指针,该指针为NULL,但在Print1中该this指针并没有用到。只要程序运行时没有访问不该访问的内存就不会出错,因此运行正常。在运行print2时,需要this指针才能得到m_value的值。由于此时this指针为NULL,因此程序崩溃了。

(5)

C++中我们可以用static修饰一个类的成员函数,也可以用const修饰类的成员函数(写在函数的最后表示不能修改成员变量,不是指写在前面表示返回值为常量)。请问:能不能同时用static和const修饰类的成员函数?

分析:答案是不可以。C++编译器在实现const的成员函数的时候为了确保该函数不能修改类的实例的状态,会在函数中添加一个隐式的参数const this*。但当一个成员为static的时候,该函数是没有this指针的。也就是说此时static的用法和static是冲突的。

(6)

C++中静态成员函数能不能同时也是虚函数?

分析:答案是不能。调用静态成员函数不要实例。但调用虚函数需要从一个实例中指向虚函数表的指针以得到函数的地址,因此调用虚函数需要一个实例。两者相互矛盾。 C语言C++学习交流群 496926338

如果你打算写一手好程序那么你就应该改变你对编程的看法。你要把编程看成一门艺术而你自己则是一个艺术家。那么你就不会因为懒惰和不小心而犯错。

作家会把一篇未完成的文章发表么?画家会把未完成的画作拿来出售么?歌手会在他的歌中唱没有用的歌词么?

绝不会。

对编程来说也一样。任何情况下,都别编写未经测试的半吊子代码。在你的程序未写完前,不要发布它。别编写不会使用的无用代码。这都是一些我们犯的一般性错误,因为我们喜欢在工作花更少的时间而去干其他事情。但这是不行的,迟早你都会为确保你的代码不出问题而负责。

越早的练习正确的编程方法,就对你的用户和自己越好。有时成为一个好的程序员意味着你不会犯糟糕程序员同样的错误。C语言C++学习交流群 496926338C语言程序设计初学者常犯错误集锦

未经允许不得转载:技术 » C语言程序设计初学者常犯错误集锦

相关推荐