分析编程语言缺陷的一种方法就是把所有的缺陷归于三类:
“多做之过”--不该做的做了;
“少做之过”--该做的没有做;
“误做之过”--该做了做了但是做的不对;
一、无论何时,如果你遇见这样一条语句,你可以断定它是错误的:
malloc(strlen(str)); //error
这是因为其他的字符串处理库函数几乎都包含一个额外空间,用于容纳字符串结尾‘\0’字符。所以malloc(strlen(str)+1);才是正确的!人们很容易忽略strlen这个特殊的情况。
二、“L”的故事
一个L的NUL和两个L的NULL
一个L的NUL用于结束一个ASCII字符串。 ASCII中字符0的位模式被称为‘NUL’;int num=4; switch(num) { default:cout<<"default"<<endl; case 1:cout<<"1"<<endl;break; case 4:cout<<"4"<<endl;break; }结果:4;//如果有对应的case,则与default无关;
int num=4; switch(num) { case 7:cout<<"7"<<endl; default:cout<<"default"<<endl; case 1:cout<<"1"<<endl;break; case 2:cout<<"2"<<endl;break; }结果:default
int num=4; switch(num) { default:cout<<"default"<<endl; case 1:cout<<"1"<<endl; case 2:cout<<"2"<<endl; }结果:default;
netword code() { switch(line1) { case thing1:do1();break; case thing2:do2(); if(true) { dosother(); break;//愿意是跳出本次的if语句; } initialization_machine(); break; case thing3:do3();break; default:processing(); } //但是break跳出了这里; using_initialization_machine();//导致没有执行inittialization_machine()函数; }就是因为这段简略的代码导致了AT&T历史上重大的网络故障。这里可以看出,break是跳出最近的那层循环语句或者switch语句。由于它跳出了switch语句致使initialization_machine()工作没有完成,为后面的失败埋下了伏笔。
(i=1),2,3;i赋值为1,接着执行常量2,3的运算,计算结果丢弃,最终结果为1。
i=(1,2,3);此时i的结果就是3,由于()改变了赋值语句的优先级,“,”运算符的值就是最右边操作数的值,所以最终是3.
int a,b=1,c=2; a=b=c;那么上面的例子如何进行计算呢?
char * func() { return "Hello"; //只适用于简单的字符; }(2)使用全局声明的数组;
int num[3] int *func() { num[3]=... return num; }(3)使用静态变量或数组,改变其生命周期;
int func() { static int number=10; return number; }(4)显示的分配内存 ,当然要记得释放;
int *func() { int *p=malloc(SIZE); return p; }
一般的来说,函数是可以返回局部变量的。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错。但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错。因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错。
准确的来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的)。