C 基本知識,注意點

自己在看學習C編程的過程中遇到過挺多問題,於是整理整理,一來分享自己的問題與解決方案,二來作爲自己的備忘,以後回頭看看。

先貼一張最基礎的輸入輸出相關的


下面是一些需要注意的地方:

1、extern ,全局變量;   static,靜態變量,只初始化一次。

2、數組是靜態實體,只有初始化至少一個數才能使得其餘的數有默認時

數組作爲參數傳遞給函數是以引用調用實現的,array,&array和&array[0] 都表示第一個元素的地址

int array[24];
函數調用爲:
modify(array,24)
函數原型則希望第一個參數收到整數數組
void modify(int array[],int size)


3、指針,就是包含內存地址的變量

int y = 5;
int *yPtr = &y;   //*運算符是解參考指針


4、C中使用指針和間接運算符來引用調用:通過指針來運算就是一種間接運算

int array = 5;
modify(&array,24)
函數原型表示爲:
void modify(int *array,int size){
	//其中 *array 表示5
}


5、const限定符:告訴編譯器一些變量的值是不能通過名字來修改的

const int* sPtr   表示sPtr是指向常量數值的指針,那麼數值是不能被改變的

如*sPtr= 100 ; 這就錯了,記住這裏數字是不能修改的
int*  const sPtr   表示sPtr是一個指向整數的常量指針,那麼指針指向是不能被改變的

如*sPtr=100; 這是可以的,指向沒變,改變了數值而已

    sPtr = &y;  這就不行了,這改變了指針的方向

const int * const sPtr = &x; 則sPtr不能爲左值,兩者都不能改

----------------------------------------------------------------------------------------

關於指針,這裏再討論一種情況:《c++ primer plus》第八章 函數探幽中函數重載中的一句話:“非const值賦給const變量是合法的,反之則是非法的!”,是下面這樣理解的:

//將非const值賦給const變量是合法的,反之則是非法的”
	int b =2;
	const int* a = &b;  //賦給不是賦值

	int bbb =2;
	const int* aaa = &bbb;
	int * c ;
	c = aaa;    // 這樣就不行了,報錯
	cout<<aaa<<" "<<bbb<<" "<<c<<endl;
	
//將非const值賦給const變量是合法的,反之則是非法的”只限於指針和引用之間傳遞,值之間傳遞怎麼都是合法的
	int bb =2;  
	const int aa = bb;
	cout<<aa<<endl;
	int c = aa;
	cout<<aa<<" "<<bb<<endl;
平時常常遇到的const char* 給char* 賦值報錯了,也就是這個原因了。

ps: const int* aaa = &bbb; 這樣賦值以後,如果直接修改bbb 的值,那aaa的值也變了,那是不是不符合const的講法呢??在前面我也標明瞭,const限定符:告訴編譯器一些變量的值是不能通過名字來修改的,如果是採用這種偷樑換柱的辦法,const的值還是會被修改掉的。



6、double ,float 基本數據類型說明 ,下一張表是結論表

類型

比特(位)數

有效數字

數值範圍

float

32

6~7

-3.4*10^38+3.4*10^38

double

64

15~16

-1.7*10^-308~1.7*10^308

long double

128/

18~19

-1.2*10^-4932~1.2*10^4932

以float爲例,如下表

符號

尾數

指數

1

23

8

數符(+-

小數部分(決定精度)

-127~128 指數(決定範圍)

        +1.1111111111111111111111*2^127(小數點後面23個1,由於尾數的範圍1~2,其最高位總爲1,故只需存取小數部分,所以小數爲是23位1),約等於2*2^127=3.4*10^38。爲3.4*10^38負數亦然。
        Double的計算與此類似,double的符號位爲63位,指數爲62~52位,共11位。表示的範圍爲-1024~1023。尾數爲51~0。表示的範圍爲+1.1111111111111111..11111*2^1023(小數點後面52個1)爲1.7*10^308。負數亦然。

       有些說法:“對編程人員來說,double 和 float 的區別是double精度高,有效數字16位,float精度7位。但double消耗內存是float的兩倍,double的運算速度比float慢得多,C語言中數學函數名稱double 和 float不同,不要寫錯,能用單精度時不要用雙精度(以省內存,加快運算速度)。” 上面能說明一些問題,但也不是絕對,比如嵌入式編程,或者在特定環境下,一般情況下在目前的硬件條件下還是推薦用double吧。

     另外有些人用printf輸出double時發現只有6位小數,不是16位精度嗎??其實double的意思是可以有16位有效數字而在固定格式輸出的時候,都默認的是6位,如果要輸出特定位數可以這樣:“ %10.5f 保留十位有效數字 五位是小數 ”


7、字符處理庫(ctype)的函數說明

       他是包含了一些對字符數據進行測試和處理的函數,每個函數接收一個字符,並且將字符作爲整數來處理,下面是簡單用法說明



8、實用程序庫(stdlib)函數說明

       這裏先介紹將數字字符串轉化爲整數和浮點數值的一些函數

     首先看下atof,字符串轉換爲double,不會丟失精度

double a = 0;
a = atof("120.34567890345678");
printf("%13.10f",a);
//輸出結果120.34567890345678未丟失精度
     然後看strtod函數,一個參數是字符串(char*),另一個是指向字符串的指針(char**),該函數時將字符串中的數字部分識別出來並轉化,把後面的字符位置賦值給第二個參數(數字字串要在最前面吧)。

      strtol()函數也類似,加了一個參數,第三個參數表示要轉換的基數,如8進制,10進制,基數可以規定爲0或者2~36之間的任何數字,另外也是檢測到第一個非法字符時,立即停止檢測,其後的所有字符都會被當作非法字符處理


9、char*  ,char[] 

       char *p="abc123ABC";   //char p[]="abc123ABC"

       char* p是一個指針,根本沒分配內存,他指向的"abc123ABC" 是隻讀的,不能改變,如果這個時候要用strcpy()函數把一個值賦值給char *p,肯定是錯的
       char p[]是一個數組,已經分配內存,是將"abc123ABC" 複製到該內存裏面,這個內存是可讀寫的

       在函數strcpy(char* s1, const char * s2)中,這裏需要注意的是s1是數組,而不是自己定義的char* 字符串,不是說把const的值賦值給非const 的值(那是指針的賦值),這個函數指的是將s2字符串複製到s1指向的區域中,改變的是數據,而不是僅僅是指針.

      如在下面的例子中賦值給a那就不行了,這裏和b是不是const倒是沒有關係。

        char * a  = "a";
	char aa[] = "aa";
	const char * b  = "b";

	strcpy(a,b);   //這樣就不行了,因爲a指向的區域是const的,不能改變的,試圖改變則會報錯
	strcpy(aa,b);  //複製到數組中是可以的



發佈了39 篇原創文章 · 獲贊 15 · 訪問量 35萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章