By:LShang
Blog:http://www.cnblogs.com/LShang
提示一
如果遇见了这样一条语句 malloc(strlen(str));,几乎可以断定它是错误的,而 malloc(strlen(str)+1);才是正确的。这是因为其他的字符串处理库函数几乎都包含了一个额外空间,用于容纳字符串结尾的‘\0’字符。所以,人们很容易忽略 strlen 这个特殊情况。
提示二
一个 ‘L’ 的 NUL 用于结束一个 ASCⅡ 字符串,ASCⅡ字符串中的零的位模式被称为 ‘NUL’
两个 ‘L’ 的 NULL 用于表示什么也不指向(空指针),哪里也不指向的特殊指针值是 ‘NULL’
C 语言多做之过
由于存在 fall through,switch 语句会带来麻烦
default 可以放到语句中的任意位置,在所有 case 语句均不匹配时执行 default 后边的语句(不会因为 default 语句在 case 语句之前而优先执行)
int main()
{
switch(2)
{
case1:
printf("Case 1!");
break;
default:
printf("Default!");
break;
case2:
printf("Case 2!");
break;
}
return0;
}C:\Turboc2>tcc test
Turbo C Version 2.0 Copyright (c) 1987, 1988 Borland International
test.c:
Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland International
Available memory 440762
C:\Turboc2>test
Case 2! // 并未因为 default 语句写在 case 2 语句之前而优先执行 default 语句switch 的左花括号之后可以定义一些变量,从而进行一些局部存储的分配(这些变量是无法被初始化的,因为 switch 语句将会从 case 语句开始执行)
int main()
{
switch(2)
{
int a;
case1:
a = 1;
printf("a = %d!",a);
break;
default:
printf("Default!");
break;
case2:
a = 2;
printf("a = %d!",a);
break;
}
return0;
}C:\Turboc2>tcc test.c
Turbo C Version 2.0 Copyright (c) 1987, 1988 Borland International
test.c:
Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland International
Available memory 440758
C:\Turboc2>test
a = 2! // 变量 a 定义成功,并成功对其赋值和使用int main()
{
switch(3)
{
int a = 3;
case1:
a = 1;
printf("a = %d!",a);
break;
default:
printf("a = %d!",a);
break;
case2:
a = 2;
printf("a = %d!",a);
break;
}
return0;
}C:\Turboc2>tcc test
Turbo C Version 2.0 Copyright (c) 1987, 1988 Borland International
test.c:
Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland International
Available memory 440730
C:\Turboc2>test
a = 1334! // 对变量 a 的初始化并未完成当需要一个临时变量时,如果有可能的话,尽量避免使用局部变量。编译器可以自由的忽略它,它可以通过函数调用来分配所有局部块需要的内存空间。另一种用法是声明一些完全局部于当前块的变量。
int main()
{
int a = 1;
int b = 2;
printf("a = %d,b = %d\n",a,b);
if(a<b)
{
int temp = a; /* 定义一个完全局限于当前块的变量 */
a = b;
b = temp;
}
printf("a = %d,b = %d\n",a,b);
return0;
}C:\Turboc2>tcc test
Turbo C Version 2.0 Copyright (c) 1987, 1988 Borland International
test.c:
Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland International
Available memory 441172
C:\Turboc2>test
a = 1,b = 2
a = 2,b = 1int main()
{
int a = 0;
for(; 3>a; ++a)
{
int b[3] = {0}; /* 定义一个完全局限于当前块的变量 */
b[a] = a;
printf("b[%d] = %d\n",a,b[a]);
}
return0;
}C:\Turboc2>tcc test.cTurbo C Version 2.0 Copyright (c) 1987, 1988 Borland International
test.c:
Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland International
Available memory 439884
C:\Turboc2>test
b[0] = 0
b[1] = 1
b[2] = 2switch 内部的任何语句都可以加上标签,并在执行时跳转到那里,这样就有可能破坏程序流的结构化
int main()
{
switch(1)
{
do_goto:
case2:
printf("2\n");
case3:
printf("3");
default:
break;
case1:
printf("1\n");
goto do_goto;
}
return0;
}C:\Turboc2>tcc test.c
Turbo C Version 2.0 Copyright (c) 1987, 1988 Borland International
test.c:
Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland InternationalAvailable memory 440668
C:\Turboc2>test
1
2
3const 关键字并不表示真正的常量
#define TWO 2 /* 用宏来定义常量 */
int main()
{
constint one = 1;
switch(1)
{
case one:
printf("1");
break;
case TWO:
printf("2");
default:
break;
}
return0;
}C:\Turboc2>tcc test
Turbo C Version 2.0 Copyright (c) 1987, 1988 Borland International
test.c:
Error test.c 7: Constant expression required in function main
Warning test.c 16: 'one' is assigned a value which is never used in function mai
n
*** 1 errors in Compile ***Available memory 442438
fall through:如果 case 语句后面不加 break,就依次执行下去,以满足某些特殊情况的需求。
break:跳出离自身最近的那层循环或 switch 语句。
相邻的字符串常量将被自动合并为一个字符串
旧风格
int main()
{
printf("Hello \
World");
return0;
}新风格
int main()
{
printf("Hello "
"World");
return0;
}这种自动合并意味着字符串数组在初始化时,如果不小心漏掉一个逗号,编译器将不会发出错误信息,而是悄无声息的将两个字符串合并在一起。。。
int main()
{
char *str[] =
{
"Hello",
"LShang",
"By"/* 没写逗号 */
""/* 没写逗号 */
"LShang", /* 多了一个逗号 */
};
printf("%s",str[2]);
return0;
}C:\Turboc2>tcc test.c
Turbo C Version 2.0 Copyright (c) 1987, 1988 Borland International
test.c:
Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland InternationalAvailable memory 440216
C:\Turboc2>test
By LShang最后一个字符串末尾的逗号不管存在与否都没有什么意义,也无法在其他由逗号分隔的列表中使用
int main()
{
int
a,
b,; /* 单行多变量声明,末尾多写一个逗号 */
return0;
}C:\Turboc2>tcc test
Turbo C Version 2.0 Copyright (c) 1987, 1988 Borland International
test.c:
Error test.c 5: Declaration syntax error in function main
*** 1 errors in Compile ***Available memory 443554
可以通过 static 来声明静态变量,表示该变量的值在各个调用之间一直保持延续性
void fun()
{
static int i = 0;
printf("i = %d\n",i);
++i;
}
int main()
{
fun();
fun();
fun();
return0;
}C:\Turboc2>tcc test.c
Turbo C Version 2.0 Copyright (c) 1987, 1988 Borland International
test.c:
Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland InternationalAvailable memory 440234
C:\Turboc2>test
i = 0
i = 1
i = 2
太多的缺省可见性
定义 C 函数时,在缺省情况下函数的名字是全局可见的。
function apple(){ /* 在任何地方均可见 */ }
extern function apple() { /* 在任何地方均可见 */ }static function apple() { /* 在这个文件之外不可见 */ }
C 语言误做之过
C 语言的符号重载
C 语言中类似的符号具有多种不同意义
sizeof 并不是一个函数而是一个操作符
当 sizeof 的操作数是歌类型名时,两边必须加上括号,但操作数如果是变量则不必加括号
apple = sizeof(int) * p;表示 apple 是 p 个 int 值占用的大小
apple = ( sizeof(int) )*p;
表达式整体解析式是从左到右的,所以 sizeof 和 * 优先级一样时,先解析左边,也就是 sizeof(int) ,如果再解析 * 为取指针的值,那表达式就不合法了。
C 语言的运算符优先级
C 语言中有些运算符的优先级是不正确的(但却很难得以改正,因为如果修改了运算符优先级,那么大量现有的代码就会出现问题)
在表达式中如果有布尔运算、算术运算、位操作等混合运算,应该在适当的地方加上括号,使之清楚明了。
结合性:在几个操作符具有相同的优先级时由结合性来决定先执行哪一个。
结合性只用于表达式中出现两个以上相同优先级的操作符的情况,用来消除歧义。
所有优先级相同的操作符,他们的结合性也相同。