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