程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> [C陷阱和缺陷]語義缺陷

[C陷阱和缺陷]語義缺陷

編輯:關於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

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved