天天看點

把《c++ primer》讀薄(1-2前言+變量和基本類型)

督促讀書,總結精華,提煉筆記,抛磚引玉,有不合适的地方,歡迎留言指正。

一:大小端的概念

二:浮點數的機器級表示

三:c++的基本的内置類型:

1)算術類型,又包括:

整型(包括:整數int、short、long int類型,單個字元(分為存儲單個機器位元組的char類型,1個位元組,char有三種不同的類型,普通char,unsigned char和signed char,一共兩個表達方式unsigned char和signed char。和存儲漢字和日語等的擴充字元集的wchar_t類型,2個位元組),布爾值0,1)。

整型又分為無符号和有符号的(除bool類型之外)

在選用整數類型的時候,一定先分析好大概範圍,一些機器int和long int一樣,如果貿然總使用範圍很大的類型,則額外代價較高,總用範圍嬌小的,又容易溢出。

浮點型,float,double,long double。一般用double就足夠了,且很多經典書籍都建議使用double,少用long doouble,因為一沒必要那麼高精度,二運作起來代價額外很大。

2)還有一種void ,空類型。

問題1:在輸出漢字字元串的時候會亂碼,一般解決方案是字元串前面加l,why?

這是在說明字元串的字面值是寬字元wchar_t,  l"大家好!"   這樣表示就可以了。因為編譯器有時候預設使用unicode字元集,不加l顯示的日文或者韓文,l代表寬字元

問題2:針對模的問題

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

4294967296模4294967296就是0

//%運算符隻能用于整數相除求餘,運算結果的符号與被除數相同,絕對不能用于實數。

//被除數=商 x 除數 + 餘數

//餘數的絕對值一定小于除數的絕對值

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

問題3:沒有short類型的字面值常量

字面值常量比如:

有無符号int類型111u,有預設帶符号的int類型111,有long int類型111l,有無符号long int類型111lu或者111ul,有預設的double類型,1.1,有單精度類型1.1f,有擴充精度類型1.1l,有true,false的bool字面值,有字元和字元串類型的字面值。就是沒有short int類型字面值!

問題4:多行字面值的表示

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

針對第三行代碼,\  雖然可以實作多行字面值字元串的輸出輸入,但是有局限,\  必須在本行末尾,後面不能有注釋和其他字元,且後續行bbbb前面的空,都算作了字元串字面值的一部分,故出現如圖第三行所示的情況,解決辦法:

問題5:程式盡量的不要過多的依賴機器

比如,int在win32下是一個長度,也許換個機器就不一樣了,如果有,最好是在依賴處都有說明,否則程式移植起來很困難。

問題6:c和c++的變量為什麼要先聲明還要定義名字,使用前為什麼還必須先定義變量或者常量的類型?

c/c++是靜态類型的語言(編譯時做類型檢測),對程式的操作是否合法都是在編譯期間檢測,故編譯器必須能夠識别程式内每個實體,對于不是關鍵字的且沒有呗引号括起來的符号,對于c/c++編譯器來說,它是不認識的,如何讓編譯器知道這個單詞是什麼意思呢?

是以就有了聲明(declare)。編譯器每次開始工作,不知道有哪些變量,不知道有哪些函數,也不知道有哪些符号常量,它不是人!如從代碼裡讀了一個單詞,既不是關鍵字,又不是自己認識的東西,編譯器就認為這是一個沒有聲明的東西,因為不認識它,是以不知道如何處理。是以“聲明”,就是告訴編譯器有這麼一個東西。聲明的時候主要做四件事: 

一是建立變量符号表

聲明變量,編譯器可以建立變量符号表,如此,程式用到多少變量,每個變量類型是什麼,編譯器非常清楚,是否使用了沒有聲明的變量,編譯器在編譯期間就可以發現,進而幫助了程式員遠離由于疏忽而将變量名寫錯的情況。 

二是變量的資料類型訓示系統配置設定多少記憶體空間

資料類型訓示系統如何解釋存儲空間中的值。同樣的數值,不同的類型将有不同的解釋。32位機器,一般情況下,int占4個位元組,float占4個位元組,在記憶體中同樣存儲二進制數,且這個二進制數也沒有标志區分目前是int還是float型,那麼如何區分?就是通過變量的資料類型來區分。由于聲明建立了變量符号表,是以系統知道變量存儲空間該如何解釋。

三是變量的資料類型确定了該變量的取值範圍

例如短整型short的資料取值-32768~32767之間。

四是不同的資料類型有不同的操作

比如,模運算,不能用于浮點數。如下:

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

問題7:了解初始化和指派是兩個完全不同的概念

c++支援兩種初始化方式,複制初始化(使用=),和直接初始化(常用于構造函數的初始化清單),且使用直接初始化,文法更靈活,效率更高(對内置類型沒什麼差別),專家推薦多用!

初始化:建立新的變量,并給變量賦一個初始值的過程。

指派:變量早在前面聲明過,且有了初始值,此時再給它一個新值(把前面的值擦掉)的過程。

注意

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

問題8:關于自動初始化

在函數外定義的變量自動初始化為0,函數内就不會自動初始化,且對于c和c++的基本内置類型,最好定義的同時就初始化,即使當下沒用。

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

針對c++,還需要考慮類的構造函數

問題9:變量定義和聲明的差別

因為c和c++經常是多檔案開發,故有了聲明和定義

變量的定義是為了給變量配置設定記憶體,指定初始值,一個變量隻能有一個定義存在。

聲明變量,是告訴程式變量的類型和名稱

即定義也是聲明,因為定義變量的同時,也聲明了變量的名字和類型,一個變量可以有多次聲明,但是定義隻有一次!因為聲明僅僅指定名稱和類型,不配置設定記憶體!

通常用關鍵字extern專門進行變量的聲明,而不定義。告訴本檔案,這個變量已經定義在了其他檔案。俗稱外連結。

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

同樣,聲明也可以變為定義,如果聲明有初始化,那麼就變為定義,針對extern語句僅僅在函數外部(擁有檔案作用域範圍),才可以變為定義,否則出錯!

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

回憶,多檔案開發,都是在一個檔案進行變量的定義,而其他檔案使用這些變量就僅僅需要包含這些變量的聲明 即可,無需(也不可以)重定義。

再看:

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

問題10;避免寫死

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

這樣做,如果常量定義出錯,或者被無心的修改,那麼可以被編譯器立馬檢測出來!程式健壯性提高!因為常量定義後不能被修改,故常量定義的同時必須馬上初始化!

問題11:引用初步探讨

多個方法定義多個引用沒問題,記住:引用就是外号而已!不占新的記憶體空間,和原數值共享記憶體空間。

注意,引用必須初始化!因為引用必需要綁定到一個實體對象!故不能是引用的引用。也不能不初始化!

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

引用一旦綁定一個對象,不能再綁定其他對象

引用要注意字面值常量的綁定問題

同理,const常量必須用const引用來綁定!

注意引用和不同類型變量的綁定問題

原因:對于不同類型的引用綁定過程,編譯器内部做了這樣的優化,先針對int類型的i = 512,自動生成一個double類型的臨時變量

再讓double引用去綁定temp,而不是我們看到的直接綁定int i=512;

故這裡有一個問題,現在refi是非const類型,那麼說明可以對refi也就是i修改,但是事實上,我們修改隻是修改了temp,不會對原值i修改,這違背了引用的初衷,故這樣是定義為不合法的行為。同理,使用const引用就ok了,因為僅僅是使用i的值,并不修改,這樣是完全合法的。

問題12:盡量多用枚舉定義常量

//c++的枚舉類型可以省略美劇名字,也可以加上名字,枚舉本身就是常量表達式!不能修改它的成員!

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

//使用枚舉定義de 常量,是真正的常量!不受限于類的對象!且有很好的可讀性!含義的聚集性!

比如在類中定義const成員,我們不能在類裡初始化,必須建立對象的時候,構造函數初始化。看似是常量,但是針對的隻是某一個對象,其他對象的話,仍然可以去初始化屬于自己的那一份const成員。并不是真正的constant!而枚舉就無所謂這個問題。

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

//枚舉是一種類型!可以定義枚舉類型的對象,同理也可以給枚舉類型的對象指派。指派,必須是這個枚舉類型的成員,或者是同一枚舉類型的其他的枚舉對象!

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

問題13:c++也支援結構類型

差別就是c++的結構裡,可以有函數,且預設的成員通路屬性是public,而class是private。

問題14:回答問題,類a裡的private成員int a;都是誰能直接去通路?

千萬不能忘記友元!當然還有類a内部的組成部分也可以直接通路。

問題15:規範化的頭檔案

頭檔案不應該含有變量或者函數的定義!隻能有聲明!但是頭檔案也有例外,那就是頭檔案可以定義類,頭檔案可以定義編譯時就知道具體值的const對象,可以定義inline函數。

問題16:什麼是常量表達式?

編譯器在編譯的時候,就能夠計算得出表達式的明确結果的表達式!表達式由常量表示:

兩個關鍵點:一是必須是編譯的時候就能計算出明确結果的表達式,二是表達式組成部分都必須是常量,不能包含變量,比如1+2是常量表達式,整型字面值常量就是常量表達式,枚舉常量也是常量表達式!如果定義a為常量1,那麼a+2也是常量表達式。如果定義變量a,那麼a+2就不是常量表達式。

問題17:解答前面const對象預設在函數外部定義,為什麼是局部作用域?(需顯式的加extern才是全局的,不同于一般變量)

15說了,頭檔案隻能有聲明,但是const常量的定義卻可以,因為c++裡,const常量在函數外部定義的話,c++規定為局部變量(本檔案可見,而本檔案外的本程式其他檔案不可見),故不會造成重定義現象。

注意更深層次的原因:

如果const對象使用常量表達式初始化,那麼該變量(變為常量的變量,僅僅說的是這個變量,不是常量表達式本身!)不會被配置設定記憶體空間,因為絕大部分的編譯器編譯時,都直接使用的相應的常量表達式來替換掉該const變量,這需要了解!是以,如果const對象在頭檔案内的函數外部沒有被常量表達式初始化,那麼就不應該定義在頭檔案,應該和其他變量一樣定義在源檔案并初始化。然後在頭檔案添加extern聲明即可被共享。比如:

這裡具體意思應該是說,頭檔案的const,一方面,定義在了函數外部,是局部作用域,局部的那就是互不影響!另一方面,就是大部分const變量都是用常量表達式初始化!上面說了,編譯器不會為這樣的const變量配置設定記憶體,而是使用對應的常量表達式替換該變量名!等價于,聲明!那麼這裡有一個名詞叫:

常量折疊

至今沒有找到一些權威的論證,網上的各個論壇部落格,都說的有一定的道理,但是具體細節又各有不同的争論,還沒有什麼權威的說法,具體涉及到了編譯原理的知識。

再說說c語言裡的const常量

《c primer plus》一書清晰的說到:c語音裡的const定義的常量,不被看為常量,而是隻讀變量!《c和指針》一書也說到,c中const定義的常量,僅僅能用在應該使用變量的地方,比如設定數組維數,使用const定義的常量就報錯!當然這是c99之前。如今c99也支援了這一做法!如下:

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

問題18:給頭檔案設定頭檔案保護符,避免重定義,也就是多重包含

把《c++ primer》讀薄(1-2前言+變量和基本類型)
把《c++ primer》讀薄(1-2前言+變量和基本類型)

辛苦的勞動,轉載請注明出處,謝謝……http://www.cnblogs.com/kubixuesheng/p/4116354.html

繼續閱讀