變量和基本類型(基於c++)

變量和基本類型(基於c++)

1. 基本內置類型

  • 算術類型: 字符、整數、布爾值、浮點數
  • 空類型:不對應具體的值,用於特殊場合

1.1 算術類型

  • 整型(布爾,字符)
  • 浮點型

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-kqLVeZ2O-1582781339653)(算術類型.png)]

1.1.1 存儲
  • 字節佔8比特
  • 字佔32或64,也就是4~8字節

每個字節與一個數字(地址)關聯

浮點型的第一個字節是ISO-Latin-1字符集,則就是分號,所以可以知道是浮點型

  1. 浮點型
    1. float 32比特
    2. double 64比特
    3. long double 96~128比特
  2. 字符型
    1. char 8比特
      1. signed char 8比特
    2. unsigned char 8比特

1.2 類型轉換

​ unsigned char c = -1; // c =255

​ signed char c = 256; //c2 未定義

  1. 含無符號的表達式

    • 例如:整數和無符號的運算會自動轉化成無符號

      unsigned u = 10;
          int i = -42;
          cout << i+i << endl;
          cout << u+i << endl;
          //-84
          //4294967264 32位
      
    • 無符號的負數時爲取模後的值

1.3 字面值

20 十進制 024 八進制 0x14 十六進制

  • 字符串的組成是字符數組(字符串的末尾多一個‘\0’)

    //分開字符串寫法
    std::cout << "你好"
         "NO" << std::endl;
    // 你好NO
    

1.4 轉義序列

​ [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rYyXVvIc-1582781339659)(轉義.png)]

  • 也可以用\x 十六進制 \八進制

  • 數值對應的字符集[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-AWvPvoHn-1582781339661)(image-20200226084101078.png)]

    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-bSmDEumQ-1582781339663)(image-20200226084332828.png)]

​ UL 會根據數值決定是unsigned long 還是unsigned long long

  • 前綴爲字符
  • 後綴爲整型或浮點型
  • aen的後面數值表示a*10n

2. 變量

何爲對象?


對象 :是指一塊能存儲數據並具有某種類型的內存空間。

對象也叫變量,而值是隻讀數據

2.1 初始值

    ///a 先被定義然後賦值, 隨後用於初始化b
    double a = 1.1, b = a*2;
  • 列表初始化 int a{0};

2.2 變量聲明和定義

​ C++語言支持分離式編譯機制,可分成若干個文件獨立運行。

  • 聲明:變量聲明規定了變量的類型和名字,不分空間
  • 定義:申請存儲空間,也可能給變量賦初始值
extern int i; // 聲明i並非定義i
int j; //聲明j並定義j

變量只能被定義一次,但可以聲明很多次

2.3 表示符

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HueBUExx-1582781339664)(image-20200226103919393.png)]

2. 4 名字的作用域

  • 全局作用域
  • 塊作用域
2.4.1 外層作用域
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int reused = 42;//全局
int main(){
    int unique = 0; // 塊
    cout << reused << " " << unique << endl;
    int reused = 0;
    cout << reused << endl; //局部覆蓋了全局
    cout << ::reused << endl; //全局
    {
        int reused = 5;
        cout << reused <<endl; //局部覆蓋局部
        cout << ::reused <<endl; //全局
    }
    return 0;
}

3. 複合類型

一條聲明語句由一個人基本基本數據類型 和一個聲明符列表組成

3.1 引用

c++11添加的 右值引用

  • 定義:爲對象起另外一個名字,引用類型引用另一種類型通過將聲明符寫成&d的形式。
  • 引用必須初始化
  • 引用並非對象
    int i, &ri = i;
    i = 5; ri = 10;
    cout << i << " " << ri << endl; //10 10
	int &r = 0; //錯誤 不能是值

3.2 指針

​ 指針是“指向”另外一種類型的複合類型。實現了間接訪問。

指針存放的是變量地址

int i;
int *pi = &i;
int *p = pi;

指針的四個狀態

  • 指向一個對象
  • 指向緊鄰對象所佔的空間的下一個位置
  • 空指針
  • 無效指針

在指針前面加*號得到指針p得對象。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-BNIvwbhU-1582781339666)(image-20200226125751785.png)]

空指針

int *p1 = nullptr;//c++11得特殊字面值
int *p2 = 0;
int *p3 = NULL; //include <cstdlib>

注意不能給指針賦int變量。

3.2.1 void* 指針

void *是一種特殊的指針,可以存放任意對象的地址

double obj = 3.14, *pd = &obj;
void *pv = &obj;
pv = pd;
  • void* 指針只能比較
  • 作爲函數的輸入輸入輸出
  • 做另一個void*指針賦值
  • 其他不能操作
3.2.2 指向指針的指針

理解看法:

  • 把變量名和前面的分開
    • 如 int **p;
    • 可以看出 int * 類型的指針* 變量名爲p

3.3 複合類型

  • 聲明

    例子:

    int* p1, p2; //p1是指向int的指針,p2是int
    int ival = 11;
    int *pi = &ival; //指向ival的指針
    int **ppi = &pi; //指向指針的指針
    

    按我的理解聲明可以從右向左看問題,它是什麼就看變量前一個字符,如果是*它指針 其他前面的東西都是它的類型,如果是&那它就是引用,其他前面的都是類型

    例如:

    int i = 42;
    int *p;
    int *&r = p; ///它是引用,是int指針型的
    r = &i;
    *r = 0;
    

4 const 限定符

有時我們希望, 定義一個值不會改變的變量

const int buf = 512; //常量
const int i = get_size(); //正確
const int k; //錯誤
int f = 9;
const int c = f; //正確
  • const 對象一旦創建就不能改變,所以一定要初始化

  • const 對象只能再自身文件內使用,多文件的情況下不能共享// 但我的嘗試發現可以共用的。。

    • 但是也有解決辦法如下:

    • 不管是聲明還是定義都添加extern關鍵字

      //file.cc 定義並初始化一個常量,可以給其他文件訪問
      extern const int buf = 5;
      //file.h 頭文件
      extern const int buf; //與file.cc 中的buf一樣
      
  • const 引用

    const int k = 5;
    const int *p = &k;
    int i = 42;
    const int &r1 = i; //常量引用是允許綁定普通int對象,但不能返過來
    const int &r2 = 5;
    int &r4 = r1*2; //錯誤
    double dval = 3.14; 
    const int &r5 = &dval; ///3 相當於const int tem = dval;const int &r5 = tem;
    //這就是臨時量
    
    • const引用的作用
    int i = 42;
    int &r1 = i;
    const int &r2 = i;
    r1 = 0; //正確
    r2 = 0; //錯誤 ,不能通過r2進行更改,但r2可以訪問i;
    
4.1 指針和const

指向常量的指針

const double pi = 3.1;
double *ptr = &pi; //錯誤和引用一樣類型不對,不能返過來。但常指針可以指向普通double
const double *cp = &pi; //正確
4.1.1 const 指針
  • 指針是對象引用不是

  • 常量指針必須初始化

  • 把*放在const 前說明指針是一個常量,不變的是指針本身的那個值而不是非指向的那個

    int err = 0;
    int *const cur = &err; //cur一直指向err 但它能操作err的值
    const double pi = 3.1;
    const double *const pip = &pi; //指向常量的常指針
    
    
4.1.2 頂層const
  • 頂層表示指針本身是個常量
  • 底層表示指針所指的對象是着常量
int i = 0; //const的類型
int *const p1 = &i; //不能改變p1的值,頂層
const int ci = 42; //不能改變ci的值, 頂層
const int *p2 = &ci //允許改變p2的值,底層
const int *const p3 = p2; //靠右的是頂層,靠左的是底層
const int &r = ci; //用聲明引用的都是底層
  • 一般非常量可以換常量,反之不可

4.2 constexpr 和常量表達式

常量表達式 指值不會改變,且在編譯過程中能得到計算結果的表達式

const int max_files = 20; // 是常量表達式
const int limit = max_files+1; // 是
int i = 27; //不是
const int sz = get_size(); //不是,直到運行才能獲得的不是

c++11的新規定, constexpr類型是驗證是否是常量表達式的,聲明constexpr肯定式個常量,且必須式常量表達式

constexpr int mf = 20; // 是
constexpt int sz = size(); // 只有當size是個constexpr函數是才正確
4.2.1 指針和constexpr

必須明確一點,constexpr只對指針有效,對所指的變量不影響

const int *p = nullptr; //p是一個指向整型常量的指針
constexpr int *q = nullptr; //q是一個指向整數的常量指針
//且它所指向的必須要在函數體外

5. 處理類型

5.1 類型別名

是一個人名字,爲了讓複雜的名字變得簡單明瞭

兩種方法:

typedef double wages; //同義詞
typedef wages base, *p; //base 是double的同義詞,p是double*的同義詞

c++11的新規則:別名聲明定義類型的別名

using SI = Sales_item; //SI 與Sales_item同義詞
5.1.1 一些複雜複合例子
typedef char *pstring;
const pstring cstr = 0; //cstr 是指向char類型的常量指針
const pstring *ps; //ps 是一個指針,它的對象是指向char的常量指針
  • 以上可以看出不能完全安照原來的樣子去用

5.2 auto 類型說明符

編程時常常需要給表達式的值賦給變量,這就要求變量清楚知道表達式的類型

所以c++11引入auto類型說明符,能通過初始值推算變量類型。

  • auto變量必須有初始值
auto item = val1+val2; //item初始化爲相加的結果
auto i = 0, *p = &i; //正確:i是整數、p是整數指針
auto sz = 0, pi = 3.14; //錯誤兩個的類型不同
int as[3][4];
auto (&row)[4] = as[1]; //錯誤auto 對於auto 默認查找到的返回值是指向as[1][0] 的指針;引用不能是數組,只能是數組類型的引用,因爲爲引用不是對象
auto &row = as[1]; //這樣就是可以的。
5.2.1 複合、常量、auto

當編譯器推斷出來的auto類型有時候和初始值不完全一樣,會事到改變結果類型,使其符合

int i = 0, &r = i;
auto a = r; //a是一個整數(r是別名)

  • auto 會忽略頂層const,同時底層const會保留。(個人理解就是相當於它的變量都不是常量,都可以修改)
const int ci = i, &cr = ci;
auto b = ci; //是整數頂層被忽略了
auto c = cr; //是整數ci本身是頂層的
auto d = &i; //是一個整數指針
auto e = &ci; //是一個指向整數常量的指針
  • 如果希望是頂層const ,指明就行

  • 還可以引用

    const auto f = ci;
    auto &g = ci; //是一個整數常量的引用
    

5.3 decltype 類型指示符

c++11 新標準引入的第二種類型說明符 decltype

  • 作用是選擇並返回操作數的數據類型
  • 編譯器飯分析表達式並得到他的類型,卻不實際計算值
decltype(f()) sum = x; //sum的類型就是函數f的返會類型
  • decltype 處理頂層const 和引用的方式與auto有些不同

    const int ci = 0, &cj = ci;
    decltype(ci) x = 0; //x的類型是const int
    decltype(cj) y = x; //y的類型是const int&, y綁定到變量x
    decltype(cj) z;   //錯誤引用必須初始化
    int i = 42, *p = &i, &r = i;
    decltype(r+0) b; //正確了加法的返回時是int型
    decltype(*p) c; //錯誤:c是int &,要初始化
    
    • 有些表達式返回引用類型(之後再細講)
    • 這裏的因爲*指針的結果其實就是 int& 而並非int,它相當於別名
  • 表達式里加上括號也可能會有所不同

  • 變量是一種作爲賦值語句左值的特殊表達式。加上括號就是引用類型了

    decltype((i)) d; //錯誤引用,要初始化
    decltype((i+5)) e; //正確
    
    • 變量加兩層括號就是引用

6. 定義數據結構

c++允許自定義數據類型,而庫類型,也是以類的形式定義的。

struct Sales_data {
    std::string str;
    unsigned un = 0;
    double do = 0.0;
};
  • 內部定義的名必須唯一與外部可重複跟局部變量類似
struct Sales{...} a, *c;
Sales kk, *ks;

跟c語言種的結構體類似。

c++11新規定。可以爲數據成員提供一個類內初始值。

6.1 編寫自己的頭文件

爲了確保各個文件中類的定義一致,類通常定義再頭文件中,頭文件和類名一樣。

  • 頭文件也能用其他頭文件的功能。
  • 使用用過其他頭文件的頭文件,也需要再一次包含它所用過的頭文件

預處理器:

#include: 指定頭文件

#define:預處理變量

​ 頭文件保護符用於檢測預處理變量:

#ifdef //當且僅當變量已定義時爲真,
#ifndef //當且僅當變量未定義時爲真
當檢測爲真時,則後續操作到 #endif爲止
#ifndef STATUS_H
#define STATUS_H
#include <string>
struct sda{
    std::string bo;
    unsigned un = 0;
    double re = 0.0;
};
#endif
  • 如果爲真繼續執行
  • 如果爲假ifndef到endif之間的部分將略過

注意用多文件的時候有些軟件需要導入路徑
參考文獻:C++ Primer第五版

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章