c语言可移植性较差吗,c陷阱与缺陷--可移植性缺陷
引入
c语言是比较底层的语言,相对于c++和java等高级语言而言。c语言在许多不同的系统平台上都有各自的实现,由于各自的实现之间有细微的差别,导致了如今的移植性问题。
在书中说到,由于程序的生命期一般比硬件更长,所以应该注意语言自身的可移植性。但时至今天,这个说法或许需要更正了。
但作者的原意在于,注意可移植性问题可以使你的程序生命期更长,可施展的空间
更大。
一 c语言标准的变更
c语言标准的变更使得语言的特性更多,更方便程序的工作。但是这种变更经常不具备向后兼容性,如此要在语言的重用性和更强大的语言特性间做个选择。
二 标识符名称的限制
这种限制主要体现在其大小写和长度上面。
三 整数的大小
c语言中为编程者提供了3种不同长度的整数:shor型、int型和long型,c语言的定义中对各种类型整数的相对长度进行了规定:
1 3种类型的整数其长度是非递减的。
2 一个普通(int类型)整数足够大以容纳任何数组下标。
3 字符长度由硬件特性决定。
注: 现代大多数机器的字符长度为8位,然而,现在越来越多的c语言实现的字符长度都是16位,已处理诸如汉字之类的语言的大字符集。但是字符类型char仍然是8位的。
在32位机器上,vc6.0的编译环境下,shor类型为16位,int和long类型都是32位。
解决方法 用类型定义来定义“新的”类型,即使类型长度需要变动之需要改动类型定义即可。
如 typedef long
tenmil;//tenmil类型表示的是最大的类型
四 字符是有符号整数还是无符号整数
根据系统不一样可能有不一样的定义,但是如果需要统一的话,可以把字符转变为无符号数然后再处理。
五 移位运算符
1 在向右移位时,空出来的位可能由0或符号位的副本来填充。
2 移位计数(即移位操作的位数)的范围为[0,被移位的对象的长度)
六 内存位置0
在所有的c程序中,无用null指针的效果都是未定义的。但对于0内存地址的数据,不同的机器有自己不同的权限保护。
七 除法运算时发生的截断
例如
q = a / b;
r = a % b;
我们希望a、b、q、r之间维护以下的关系:
1 最重要的一点,我们希望q*b + r =
a,因为这是定义余数的关系。
2 如果我们改变a的正负号,我们希望这会改变q的符号,但这不会改变q的绝对值。
3 当b〉0时,我们希望保证r>=0且r
但这三条性质不能同时具备,大多数的程序设计语言选择了放弃第3条,使得性质1和性质2可以得到满足。
八 随机数的大小
ANSI
C标准中定义了一个常数RAND_MAX,它的值等于了随机数的最大取值。
九 大小写转换
库函数toupper和tolower起初被实现为宏:
#define toupper(c) ((c) + 'A' - 'a')
#define tolower(c) ((c) + 'a' - 'A')
这两个宏都依赖于特定实现中字符集的性质,即需要所有的大写字母与相应的小写字母之间的差值是一个常量。这个假定对ASCII字符集和EBCDIC字符集来说都是成立的。
十 首先释放,然后重新分配
大多数c语言实现都是用了3个内存分配函数:malloc,
realloc和free。
但是问题在于free掉的内存会被系统重新分配,但是如果在系统没有重新分配之前,再次使用这段内存的话仍能获得之前的内存内容。
例如
free(p);
p = realloc (p, newsize);
在某些系统中是允许的。
但是这种做法还是有危险的。因为并非所有的c实现按在某块内存被释放后还能较长时间地保留。
十一 可移植性问题的一个例子
原型:
void
printnum (long n, void (*p)90)
{
if(n<0) {
(*p) ('-');
n = -n;
}
if (n >= 10)
printnum(n/10, p);
(*p) ((int)(n % 10) + '0');
}
这是个打印整数的函数,以下为考虑到可移植性后经过改动的程序:
void
printeg (long n, void (*p)())
{
long q;
int r;
q = n / 10;
r = n % 10;
if (r>0) {
r - =10;
q++;
}
if (n <= -10)
printneg (q, p);
(*p) ("0123456789"[-r]);
}
修改点:
1 在字符集上0-9的字符未必是连续有序的。
2 n<0时,由于有符号数的范围一般是-2[n]~2[n]-1(2[n]表示2的n次幂,n为位数),所以当-2[n]取
正数时变为2[n]时已经溢出了。解决方法为从负数方向去解决这个问题。
后语:
考虑可移植性是个复杂和繁琐的问题,因为以后的硬件什么的怎么变化无法预计。但是,努力提高软件的可移植性,实际上延长了软件的生命期。
tips
软件中出现的很多可移植性问题或其他问题,很多时候在于边界条件上。所以在写程序时,不妨把边界条件作为一个重要的考虑点进行测试。
以下为本章的第二道联系题我的答案:
int
ctol(char ctl)
//该处在答案中不存在,但考虑到字符集自身排序问题还是在此处加上了,
//不过效率显然降低了。
{
int i=0;
char num[10] = "0123456789";
for(;i<10;i++)
{
if(num[i] == ctl)
return i;
}
}
long
atol(char *cl)
{
int result = 0;
int i = 0;
if((*cl == '+') || (*cl == '-'))
i++;
while(1)
{
if((cl[i] < '0') || (cl[i]
> '9'))
{
assert(0,
"invalid input!");
}
result = result*10 +
ctol(cli[i]); i++;
}
if(*cl == '-')
result = -result;
return result;
}
总结
以上是生活随笔为你收集整理的c语言可移植性较差吗,c陷阱与缺陷--可移植性缺陷的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: c语言将字符项链,【能量项链】 (C语言
- 下一篇: 99用c语言怎么写出来的,c语言的书写格