程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C編程常見相關問題總結

C編程常見相關問題總結

編輯:C++入門知識

本文是C編程中一些常見錯誤的總結,有些是顯而易見的,有些則是不容易發現

本文地址:http://www.cnblogs.com/archimedes/p/get-screwed-c.html,轉載請注明源地址。

1.忘記注釋結束符

代碼

a = b; /* 出現bug
c = d; /* c = d將不會執行*/

2.意外的賦值/意外的bool表達式

代碼:

if(a = b) c;  /*a恆等於b,只有當b!=0的時候才執行*/

再看下面的代碼:

if(0 < a < 5) c;   /*布爾表達式恆為真*/

上面代碼中的bool表達式恆為真,由於0 < a的值為0或1,永遠都小於5成立,當然C中沒有bool表達式,這裡只是假設

3.有缺陷的宏

代碼:

#define assign(a,b) a=(char)b
assign(x,y>>8)

變成

x=(char)y>>8    /* 可能不是你的目的 */ 

4.不匹配的頭文件

代碼:

//foo.h:
struct foo { BOOL a};
//F1.c
#define BOOL char
#include "foo.h"
//F2.c
#define BOOL int
#include "foo.h"

F1與F2對結構體foo中的BOOL類型定義不一致,如果交互就會出現錯誤

5.飄忽不定的返回值

可能你會寫下面的代碼:

int foo (a)
{ if (a) return(1); } /* bug,因為有時候沒有值返回 */

6.不可預知的結構體

看下面的比特包結構:

struct eeh_type
{
    uint16 size:          10;   /* 10 bits */
    uint16 code:           6;   /* 6 bits */
};

取決於用哪個C編譯器,還有你的機器使用大小端,這段代碼實現為:

<10-bits><6-bits> 或 <6-bits><10-bits>

同時取決於C編譯器、機器體系結構、不可思議的優先設置,這些項可能對齊到最近的8, 16, 32, or 64 bits.

7.不確定的求值順序

  foo(pointer->member, pointer = &buffer[0]);

不同的編譯器針對函數參數有不同的求值順序,gcc是從左到右的求值順序,有的編譯器是從右往左

8.容易改變的塊作用域

代碼:

if( ... ) 
      foo(); 
  else 
      bar();

當加上調試輸出信息:

if( ... ) 
    foo();          
else 
    printf( "Calling bar()" );      /* 注意! else止於此 */
    bar();                          /* 注意! bar永遠會被執行 */

9.不安全的返回值

代碼:

char *f() { 
   char result[80]; 
   sprintf(result,"anything will do"); 
   return(result);    /* 注意! result 被分配在棧上. */ 
 }

int g() 
{ 
   char *p; 
   p = f(); 
   printf("f() returns: %s\n",p); 
} 

10.未定義副作用(side effects

哪怕一個簡單的表達式,C沒有定義副作用的順序,結果取決於你的編譯器,i/i++可能等於0或1,看下面的代碼:

#include <stdio .h>
int foo(int n) {printf("Foo got %d\n", n); return(0);}
int bar(int n) {printf("Bar got %d\n", n); return(0);}
int main(int argc, char *argv[]) 
{
    int m = 0;
    int (*(fun_array[3]))();
    int i = 1;
    int ii = i/++i;
    printf("i/++i = %d, ",ii);
    fun_array[1] = foo; fun_array[2] = bar;
    (fun_array[++m])(++m);     
    return 0;
}

11.未初始化的局部變量

事實上這個bug不是那麼出名,但是一旦發生嚴重性不會輸給其他的bug,看下面的代碼:

void foo(a)
{ int b;
  if(b) {/* bug! b沒有被初始化 */ }
}

現代編譯器會發出錯誤的警告,看下面代碼:

void foo(int a) 
{ BYTE *B;
   if(a) B=Malloc(a);
          if(B) { /* BUG! B 可能沒被初始化 */ *b=a; } 
}

12.雜亂的編譯時環境

編譯時環境產生成百上千的編譯信息,我們對此知之甚少。有些危險的常用名,導致很難被發現:

#include <stdio.h>
#define BUFFSIZE 2048 
long foo[BUFSIZ];   //注意拼寫: BUFSIZ != BUFFSIZE

編譯器不會報錯,因為BUFSIZ已經在stdio.h中定義

13.八進制數

在C中,八進制數以0開始,如果數字中沒有‘8’或‘9’出現,編譯器不會警告

 int numbers[] = { 001,        
                           010,        // 8 而不是 10 
                           014  };     // 12, 而不是 14 

14.有符號字符

C中的有符號char可能出現各種錯誤,比如128是一個負數,另外,任何使用低精度整數都必須十分的小心,C使得這些太容易被忽略了

char s = 127;
unsigned char u = 127;
s++;      /* 結果是負數 */
if (s<u) { /* true!*/ }
if(s>127) { /* 永不可能為true */  }
if(u<0) {  /* 永不可能為true*/  }

15.糟糕的“標准庫”

代碼:

{ int a=1,b=2;
  char buf[10];
  scanf("%d %d",a,b);            // &a,&b? 
  sprintf(buf,"this is the result: %d %d"); // 溢出            
}

 

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