c语言可移植性较差吗,c陷阱与缺陷--可移植性缺陷
引入
c語(yǔ)言是比較底層的語(yǔ)言,相對(duì)于c++和java等高級(jí)語(yǔ)言而言。c語(yǔ)言在許多不同的系統(tǒng)平臺(tái)上都有各自的實(shí)現(xiàn),由于各自的實(shí)現(xiàn)之間有細(xì)微的差別,導(dǎo)致了如今的移植性問(wèn)題。
在書(shū)中說(shuō)到,由于程序的生命期一般比硬件更長(zhǎng),所以應(yīng)該注意語(yǔ)言自身的可移植性。但時(shí)至今天,這個(gè)說(shuō)法或許需要更正了。
但作者的原意在于,注意可移植性問(wèn)題可以使你的程序生命期更長(zhǎng),可施展的空間
更大。
一?c語(yǔ)言標(biāo)準(zhǔn)的變更
c語(yǔ)言標(biāo)準(zhǔn)的變更使得語(yǔ)言的特性更多,更方便程序的工作。但是這種變更經(jīng)常不具備向后兼容性,如此要在語(yǔ)言的重用性和更強(qiáng)大的語(yǔ)言特性間做個(gè)選擇。
二?標(biāo)識(shí)符名稱(chēng)的限制
這種限制主要體現(xiàn)在其大小寫(xiě)和長(zhǎng)度上面。
三?整數(shù)的大小
c語(yǔ)言中為編程者提供了3種不同長(zhǎng)度的整數(shù):shor型、int型和long型,c語(yǔ)言的定義中對(duì)各種類(lèi)型整數(shù)的相對(duì)長(zhǎng)度進(jìn)行了規(guī)定:
1?3種類(lèi)型的整數(shù)其長(zhǎng)度是非遞減的。
2?一個(gè)普通(int類(lèi)型)整數(shù)足夠大以容納任何數(shù)組下標(biāo)。
3?字符長(zhǎng)度由硬件特性決定。
注:?現(xiàn)代大多數(shù)機(jī)器的字符長(zhǎng)度為8位,然而,現(xiàn)在越來(lái)越多的c語(yǔ)言實(shí)現(xiàn)的字符長(zhǎng)度都是16位,已處理諸如漢字之類(lèi)的語(yǔ)言的大字符集。但是字符類(lèi)型char仍然是8位的。
在32位機(jī)器上,vc6.0的編譯環(huán)境下,shor類(lèi)型為16位,int和long類(lèi)型都是32位。
解決方法?用類(lèi)型定義來(lái)定義“新的”類(lèi)型,即使類(lèi)型長(zhǎng)度需要變動(dòng)之需要改動(dòng)類(lèi)型定義即可。
如?typedef long
tenmil;//tenmil類(lèi)型表示的是最大的類(lèi)型
四?字符是有符號(hào)整數(shù)還是無(wú)符號(hào)整數(shù)
根據(jù)系統(tǒng)不一樣可能有不一樣的定義,但是如果需要統(tǒng)一的話(huà),可以把字符轉(zhuǎn)變?yōu)闊o(wú)符號(hào)數(shù)然后再處理。
五?移位運(yùn)算符
1?在向右移位時(shí),空出來(lái)的位可能由0或符號(hào)位的副本來(lái)填充。
2?移位計(jì)數(shù)(即移位操作的位數(shù))的范圍為[0,被移位的對(duì)象的長(zhǎng)度)
六?內(nèi)存位置0
在所有的c程序中,無(wú)用null指針的效果都是未定義的。但對(duì)于0內(nèi)存地址的數(shù)據(jù),不同的機(jī)器有自己不同的權(quán)限保護(hù)。
七?除法運(yùn)算時(shí)發(fā)生的截?cái)?/p>
例如
q = a / b;
r = a % b;
我們希望a、b、q、r之間維護(hù)以下的關(guān)系:
1?最重要的一點(diǎn),我們希望q*b + r =
a,因?yàn)檫@是定義余數(shù)的關(guān)系。
2?如果我們改變a的正負(fù)號(hào),我們希望這會(huì)改變q的符號(hào),但這不會(huì)改變q的絕對(duì)值。
3?當(dāng)b〉0時(shí),我們希望保證r>=0且r
但這三條性質(zhì)不能同時(shí)具備,大多數(shù)的程序設(shè)計(jì)語(yǔ)言選擇了放棄第3條,使得性質(zhì)1和性質(zhì)2可以得到滿(mǎn)足。
八?隨機(jī)數(shù)的大小
ANSI
C標(biāo)準(zhǔn)中定義了一個(gè)常數(shù)RAND_MAX,它的值等于了隨機(jī)數(shù)的最大取值。
九?大小寫(xiě)轉(zhuǎn)換
庫(kù)函數(shù)toupper和tolower起初被實(shí)現(xiàn)為宏:
#define toupper(c) ((c) + 'A' - 'a')
#define tolower(c) ((c) + 'a' - 'A')
這兩個(gè)宏都依賴(lài)于特定實(shí)現(xiàn)中字符集的性質(zhì),即需要所有的大寫(xiě)字母與相應(yīng)的小寫(xiě)字母之間的差值是一個(gè)常量。這個(gè)假定對(duì)ASCII字符集和EBCDIC字符集來(lái)說(shuō)都是成立的。
十?首先釋放,然后重新分配
大多數(shù)c語(yǔ)言實(shí)現(xiàn)都是用了3個(gè)內(nèi)存分配函數(shù):malloc,
realloc和free。
但是問(wèn)題在于free掉的內(nèi)存會(huì)被系統(tǒng)重新分配,但是如果在系統(tǒng)沒(méi)有重新分配之前,再次使用這段內(nèi)存的話(huà)仍能獲得之前的內(nèi)存內(nèi)容。
例如
free(p);
p = realloc (p, newsize);
在某些系統(tǒng)中是允許的。
但是這種做法還是有危險(xiǎn)的。因?yàn)椴⒎撬械腸實(shí)現(xiàn)按在某塊內(nèi)存被釋放后還能較長(zhǎng)時(shí)間地保留。
十一?可移植性問(wèn)題的一個(gè)例子
原型:
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');
}
這是個(gè)打印整數(shù)的函數(shù),以下為考慮到可移植性后經(jīng)過(guò)改動(dòng)的程序:
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]);
}
修改點(diǎn):
1?在字符集上0-9的字符未必是連續(xù)有序的。
2?n<0時(shí),由于有符號(hào)數(shù)的范圍一般是-2[n]~2[n]-1(2[n]表示2的n次冪,n為位數(shù)),所以當(dāng)-2[n]取
正數(shù)時(shí)變?yōu)?[n]時(shí)已經(jīng)溢出了。解決方法為從負(fù)數(shù)方向去解決這個(gè)問(wèn)題。
后語(yǔ):
考慮可移植性是個(gè)復(fù)雜和繁瑣的問(wèn)題,因?yàn)橐院蟮挠布裁吹脑趺醋兓療o(wú)法預(yù)計(jì)。但是,努力提高軟件的可移植性,實(shí)際上延長(zhǎng)了軟件的生命期。
tips
軟件中出現(xiàn)的很多可移植性問(wèn)題或其他問(wèn)題,很多時(shí)候在于邊界條件上。所以在寫(xiě)程序時(shí),不妨把邊界條件作為一個(gè)重要的考慮點(diǎn)進(jìn)行測(cè)試。
以下為本章的第二道聯(lián)系題我的答案:
int
ctol(char ctl)
//該處在答案中不存在,但考慮到字符集自身排序問(wèn)題還是在此處加上了,
//不過(guò)效率顯然降低了。
{
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;
}
總結(jié)
以上是生活随笔為你收集整理的c语言可移植性较差吗,c陷阱与缺陷--可移植性缺陷的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: c语言将字符项链,【能量项链】 (C语言
- 下一篇: 99用c语言怎么写出来的,c语言的书写格