【C陷阱和缺陷】语义缺陷

一,指针和数组
1) C语言中只有一维数组,而且数组的大小必须在编译期就作为一个常数确定下来

2) 对于一个数组,我们只能够做两件事:确定该数组的大小,以及获得指向该数组下标为0的元素的指针.

例子1:
int a[3];
sizeof(a) = 12 结果是整个数组a的大小,而不是指向数据a的元素的指针的大小.
int calendar[12][30];
sizeof(calender[4]) = 120 大小为31个sizeof(int)的值
calendar[1][2] 与*(*(calendar+4)+7)等价

例子2:

对int *p进行操作,单位为一个int的大小
而对int *p[31],则每次操作的是31个int的大小
int calendar[12][31];
int **p = calendar;错误,因为单位不同
int (*p)[31] ; p=calendar;正确,单位相同
但对于字符串来说:
char calendar[12][31];
char **a = calendar;
char *a[] 与 char **a等价
正确,因为每次操作字符串,即printf("%s",a[0])这样操作,不会涉及a[1][2]这样的操作,所以每次操作单位是char *

例子3:数组中实际不存在的‘溢界’元素的地址位于数组所占内存之后,这个地址可以用于进行赋值和比较,当然,如果要引用该元素,那就是非法的
 
 

#include<stdio.h>
int main()
{
int calendar[12][31];
int (*monthp)[31];
for(monthp = calendar; monthp < &calendar[12]; ++monthp){
int *dayp;
for(dayp = *monthp; dayp < &(*monthp)[31]; ++dayp)
*dayp = 0;
}
}


二,非数组的指针的使用
 
 

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char *r;
char *s = "hi";
char *t = "man";
r = malloc(strlen(s)+strlen(t)+1); //包括最后的'/0',strlen不包括'/0'
if(!r){
exit(1);
}
strcpy(r,s);
strcat(r,t);
printf("%s\n",r);
free(r);
}

注意:malloc 可能无法正确分配内存,所以要检查是否分配成功
使用完指针,要记得释放。free(char *)
空指针并非空字符串,这个指针绝对不能被解除引用

三,求值顺序的不确定
y[i] = x[i++] 不能确定i++在什么时候被使用
改为y[i] = x[i] ; i++

四,整数溢出
在无符号算术运算中,没有溢出,只有在两个操作数都是有符号数整数时,才可能发生溢出,并且溢出的结果是未定义的。
INT_MAX是一个已定义常量,代表可能的最大整数值。在<limits.h>中定义,则可用如下方法确定是否溢出。
改变一个正整数的符号都可以保证不会发生溢出,唯一的麻烦来自于改变一个负数的符号的时候。因此,如果保证我们能够
保证不将最小负数转换为整数,就能避免。
两种方法检测:
(1)将a和b都强制转换为无符号整数
if((unsigned)a + (unsigned)b > INT_MAX)
ERR
(2)直接利用最大值
if(a > INT_MAX -b)
ERR

五,高效的二分法
(1)指针操作要比数组操作快
(2)移位运算比除法快
 
 

#include<stdio.h>
int * bsearch(int *t,int n,int x){
int *lo = t,*hi = t + n-1;
while(lo < hi){
int *mid = lo + ((hi-lo) >> 1);
//不能为int *mid = (hi + lo) / 2因为对指针进行加法是错误的,
//只能对指针进行迭代即++或--,或相减计算距离
if(x < *mid){
hi = mid - 1;
}else if (x > *mid){
lo = mid + 1;
}else{
return mid;
}
}
return NULL;
}
int main()
{
int a[] = {1,2,3,4};
printf("%d",*bsearch(a,4,2));
}


六,数组取值边界
(1)取值范围的大小就是上界与下界之差
(2)如果取值范围为空,那么上界等于下届
void bufwrite(char *p,int n)
{
while(--n >= 0)
{
if(bufptr == &buffer[N])
{
flush();
}
*bufptr++ = *p++;
}
}
当bufptr与&buffer[0]相等时,缓冲区存放的内容为空

任何时候已存放的字符数都是bufptr-buffer

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值