C和指针易错区
1.char ch;
...
while( (ch = getchar()) != EOF )
...
注意:EOF需要的位数比字符型值所能提供的位数要多,这也是getchar返回一个整型值而不是字符值的原因。然而以上程序将getchar()的返回值首先存储于ch中,这将会导致截断,程序可移植性降低。
一般的,在比较字符型与整型大小时,可以将字符型变量声明为整型变量,这样便于比较。
2.为了保持最佳的可移植性,把字符的值限制在有符号和无符号字符的范围的交集之内,即0~127。
3.sizeof( a = b+1 );语句是不会对表达式 a = b+1 进行赋值运算的。
4.++a = 10; 此语句在g++编译中是可以通过的,但在gcc编译中不能通过。即在gcc中,编译器会将 ++a 看作一个表达式,它的结果是a值的一个拷贝,而不是其本身,你只能用它;但在g++中,编译器将其看作是a本身。
5.逗号表达式是从左向右逐个进行求值,整个逗号表达式的值是最后那个表达式的值。看下面程序:
while( a = get_value(), count_value(a), a>0 )
{
...
}
其等价于:
a = get_value();
count_value(a);
while( a>0 )
{
...
a = get_value();
count_value(a);
}
6.int a = 60000;
int b = 4000;
long c = a*b;
此程序易出现问题,a*b的值可能溢出,要写为: long c = (long)a * b; 这样就进行自动类型转换了。
7.4个可以对整个表达式的求值顺序施加控制的操作符是:&&,||,?: 和 , 。
8.注意 *p++ , (1)++操作符产生p的一份拷贝(2)然后++操作符增加p的值(3)最后在p的拷贝上执行间接访问操作。另外++操作符的优先级高于*操作符。
9.标准允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但不允许与指向数组第一个元素之前的那个内存位置的指针进行比较。
10.int a[SIZE];
int* b;
b = a;
cout << b[0] ;
cout << b[-1];
cout << 2[a];
cout << 2[b];
以上cout都是合法的。
11.对于自动变量,为何不能像静态变量或者全局变量那样可以被自动赋初值。是因为自动变量位于运行时堆栈中,执行流每次进入它所在的代码块时,这类变量每次所处的内存位置可能并不相同。
12.char message[] = "hello"; char *message = "hello"; string message = "hello"; 以及 char message[] = {'h','e','l','l','o'};是相同的效果,但是要记得“hello”中是要多一个字符'\0'的。被赋值为"hello"的变量(不论是指针还是数组)都将被视为指针,当输出时,cout<< message;就会输出hello,特别注意当形式写为 char message[] = "hello"; 时cout<< message;的值,很具有迷惑性。
当联合的各个成员具有不同的长度,其的长度就是它最长成员的长度。当存储成员的长度差异较大时,为了避免内存浪费,采取存储指针。其可以初始化,但初始值只能与第一个成员的类型匹配。
19.int fun();//此为一个函数声明
int (*p)() = &fun; 或者 int (*p)() = fun;//函数名被解释为指向函数入口地址的指针
int value;
value = fun();
value = (*p)();
value = p();
以上三条调用函数语句是等价的,编译器在执行函数调用操作真正是需要函数在内存中的位置,执行是开始于其地址的,所以前两条语句是要由编译器将函数名转换为函数指针。
20.字符串常量。
cout << "xyz";// xyz
cout << "xyz"+1;// yz
cout << "xyz"[2];// z
cout << *"xyz";// x
cout << *("xyz" + 1);// y
字符串"xyz"其实质上是一个指针常量。
21.如果 一个现存的名字要被#define重新定义,那么它的旧定义首先必须用#undef移除。
22.NULL是字符串终止符,它本身并不是字符串的一部分,所以字符串的长度并不包括NULL字节,NULL其表现为 '\0' 。
23. strcmp函数返回值为int类型(1,0,-1),而非bool类型。注意错误用法if(strcmp(s1,s2))。
24.当用strncpy函数将源字符串的字符复制到目标数组,如果strlen(src)的值大于或等于len,那么只有len个字符被复制道des中,注意!其结果将不会以NULL字节结尾,而strncat函数始终都会在结尾加上NULL字符。如下程序:
char buffer[BSIZE];
strncpy( buffer, name, BSIZE );
buffer[BSIZE-1] = '\0';
这样能很好预防出现由strncpy函数得到的结果不以NULL字节结尾。