main函数只有以下两种定义方法是正确的:
int main(void)
int main(int argc, char *argv[])
main返回值的作用:
int main()
{
return 0;
}
上面的代码在Linux环境下,采用命令:
g++ main.cpp
生成可执行文件a.out,然后,执行命令:
./a.out && ehco "success"
结果输出success
如果上述程序为:
int main()
{
return -1;
}
则无输出。
注意 == 和 = 的区别,为了防止出现问题,可以通过良好的代码习惯避免。
if(0 == n)
{
// do something
}
此外还有&&和&,||和|的区别。
熟悉操作符的优先级,多写几个括号。
如:
if(n & m == k)
if((n & m) == k)
注意函数参数和操作数的评估求值顺序问题。
如:
int i = 2010;
printf("the result are: %d %d", i, i+=1);
printf("the result are: %d %d", i, i+1);
a = p() + q() * r();
int para1 = p();
int para2 = q();
a = para1 + para2 * r();
(1)使用宏定义表达式时,要使用完备的括号
如:
#define ADD(a, b) a + b
#define ADD(a, b) (a + b)
#define ADD(a, b) (a) + (b)
如果计算ADD(a, b) * ADD(c, d),本意是对(a+b)*(c+d)求值,但代码展开后变成了如下形式:
a + b * c + d
(a + b) * (c + d)
(a) + (b) * (c) + (d)
又如:
#define MULTIPLE(a, b) (a * b)
在计算(a+b)*c时,得到
(a + b * c)
要避免这些问题,要做的就是:用完备的括号完备地保护各个宏参数。正确的定义应为:
#define ADD(a, b) ((a) + (b))
#define MULTIPLE(a, b) ((a) * (b))
(2)使用宏时,不允许参数发生变化,警惕++,–等运算符。
(3)用大括号将宏定义地多条表达式括起来。
在适应局部指针变量时,一定要将其初始化。对于全局变量来说,在声明地同时,编译器会完成对变量地初始化。
例如:
if(++x, --y, x<20 && y>0)
if的判断以最后一个表达式为准。
在调用C语言字符串经典函数(如strcpy,strcat,gets等)时,尽量追踪传入数据的流向。在访问数据时,注意对边界数据要特殊情况特殊处理。还要杜绝使用未初始化指针和失效后未置NULL的“野指针”。
如:
void (*p[10])(void(*)());
改为
typedef void(*pfv)();
typedef void (*pFun_taking_pfv) (pfv);
pFun_taking_pfv p[10];
使用typedef可以让函数指针更直观和易维护。
// 解决方法1
#ifndef __SOMEFILE_H__
#define __SOMEFILE_H__
// statements
#endif
//解决方法2,仅VC++支持
#pragma once
如下面的代码:
struct A
{
int a;
char b;
short c;
}; //sizeof(struct A) = 8
struct B
{
char b;
int a;
short c;
}; //sizeof(struct B) = 12
了解结构体中元素的对齐规则,合理地为结构体元素进行布局。这样不仅可以有效地节约空间,还可以提高元素的存取效率。
// 将表达式的类型转换为T
(T) expression
T(expression)
这两种形式之间没有本质上的区别。
新风格的强制转型:
class A { //...};
void Function()
{
const A *pConstObj = new A;
A *pObj = pConstObj; //ERROR: 不能讲const对象指针赋值给非const 对象
pObj = const_cast<A*>(pConstObj); //OK
}
class B { //...};
class D: public B { //...};
void Function(D *pObjD)
{
D *pObj = dynamic_cast<D*>(pObjD)
}
浅醉操作符省去了临时对象的构造,因此它在效率上由于后缀操作。
用途:
可变参数的类型和个数在函数中由程序代码控制,导致编译器对可变参数的函数原型检查不够严格,难于查错,不利于写出高质量的代码。
void 无类型
void 无类型指针
extern "C"
对于POD对象,可以通过对象的及地址和数据成员的偏移量获得数据成员的地址,但是在C++中,非POD对象的内存布局不确定。
new/delete在管理内存的同时调用了构造和析构函数,而malloc/free仅仅实现了内存分配与释放。
malloc/free时C/C++语言的标准库函数,而new/delete是C++的运算符。
// 以及/* */
参考建议11
在预处理阶段,预处理器会完成宏替换,因为此过程并不在百衲衣过程中进行,所以难以发现潜在的错误以及其他代码维护问题。
未完待续