目錄
- 一、結構體成員訪問操作符
- 1.1 結構體
- 二、操作符的屬性:優先級、結合性
- 2.1 優先級
- 2.2 結合性
- C 運算符優先級
- 三、表達式求值
- 3.1 整型提升
- 3.2 算數轉化
- 總結
一、結構體成員訪問操作符
1.1 結構體
C語言已經提供了內置類型,如:char,short,int,long,float,double等,但是只有這些內置類型還是不夠的,假設我想描述學生,描述一本書,這時單一的內置類型是不行的。
描述一個學生需要名字,年齡,學號,身高,體重等
描述一本書需要作者,出版社,定價等。C語言為了解決這個問題,增加了結構體這種自定義的數據類型,讓程序員可以自己創造適合的類型。
注:結構是一些值的集合,這些值稱為成員變量。結構的每個成員可以是不同類型的變量,如:標量、數組、指針,甚至是其他結構體。
這里可以和數組相比較
數組:是一組相同類型的元素的集合
struct tag
{member-list;
}variable-list;//變量列表
這里的member-list可能有多個值,值叫成員變量。variable-list變量列表可有可無。
//聲明了一個結構體類型
struct Stu
{//1個或多個成員 - 這些成員都是用來描述學生的char name[20];int age;char id[11];float score;//...
} s6,s7,s8;//全局變量
其大體形式就如圖示代碼,s6,s7,s8就是變量列表,其相當于在聲明類型的時候順便創建了幾個變量,相當于全局變量,也可以不寫,在下面單獨創建。
//聲明了一個結構體類型
struct Stu
{//1個或多個成員 - 這些成員都是用來描述學生的char name[20];int age;char id[11];float score;//...
} s6,s7,s8;//全局變量,聲明類型的同時定義s6,s7,s8struct Stu s4;//全局變量,定義結構體變量s4
struct Stu s5;//全局變量int main()
{int num = 0;struct Stu s1 = {"zhangsan", 20, "2024010102", 85.5f};struct Stu s2 = {.age=18, .name="wangcai",.score=95.5f,.id = "2025010102"};//指定順序初始化struct Stu s3;//局部變量return 0;
}
編譯器在默認情況下會將85.5認定為double類型,所以要加一個f,搞成float類型。
而且在默認情況下,結構體的初始化變量只能按順序初始化,即按結構體的聲明順序來創建,如果想要指定初始化順序,就要使用操作符(.)來訪問結構體成員了。
使用方法:結構體變量.成員名
結構體也可以嵌套使用,即在結構體中引用結構體:
//聲明了一個結構體類型
struct Peo
{char name[30];int age;char tele[12];
};struct Ebook
{struct Peo data[100];//可以存放100個人的信息int count;//當前已經存的個數
};int main()
{struct Peo p1 = {"zhangsan", 20, "15598888888"};struct Ebook eb = { {{"wangwu", 19, "13396668866"},{"cuihua", 18, "18696866688"}}, 0};//printf("%s\n", p1.name);//printf("%d\n", p1.age);//printf("%s\n", p1.tele);printf("%s\n", eb.data[1].name);printf("%d\n", eb.data[1].age);printf("%s\n", eb.data[1].tele);//. : 結構成員訪問操作符//結構體變量.結構體成員return 0;
}
這里也不太好說,直接看監視窗格就懂了:
二、操作符的屬性:優先級、結合性
C語言的操作符有兩個重要的屬性:優先級、結合性,這兩個屬性決定了表達式求值的計算順序。
2.1 優先級
優先級指的是,如果一個表達式包含多個運算符,哪個運算符應該優先執行。各種運算符的優先級是不一樣的。
3 + 4 *5
該示例中,表達式3+45里既有加法運算符,又有乘法運算符。由于乘法的優先級高于加法,所以會先計算45,而不是先計算3+4.
2.2 結合性
如果兩個運算符優先級相同,優先級沒辦法確定先計算哪個了,這時候就需要看結合性了,則根據運算符是左結合,還是右結合,決定執行順序。大部分運算符是左結合(從左到右執行),少數運算符是右結合(從右向左執行),比如賦值運算符(=)
5 * 6 / 2
該示例中,*和/的優先級相同,他們都是左結合運算符,所以從左到右執行,先計算5×6,再計算/2。
運算符的優先順序很多,下面是部分運算符的優先級順序(按照優先級從高到低排列)
- 圓括號(())
- 自增運算符(++),自減運算符(–)
- 單目運算符(+和-)
- 乘法(*),除法(/)
- 加法(+),減法(-)
- 關系運算符(<、>等)
- 賦值運算符(=)
補充:圓括號的優先級是最高的,可以使用它來改變其他運算符的優先級。
C 運算符優先級
優先級 | 運算符 | 描述 | 結合性 |
---|---|---|---|
1 | ++ – () [] . -> (type){list} | 后綴/后置自增和自減 函數調用 數組下標 結構體和共用體成員訪問 通過指針訪問結構體和共用體成員 復合字面量[C99] | 從左到右 |
2 | ++ – + - ! ~ (type) * & sizeof _Alignof | 前綴自增和自減[注釋1] 單目正負 邏輯非和按位取反 強制類型轉換 間接訪問(解引用) 取地址 求大小[注釋2] 對齊要求[C11] | 從右到左 |
3 | * / % | 乘法、除法和取余 | 從左到右 |
4 | + - | 加法和減法 | 從左到右 |
5 | << >> | 按位左移和右移 | 從左到右 |
6 | < <= | 用于關系運算符 < 和 ≤ (分別對應) | - |
7 | > >= | 用于關系運算符 > 和 ≥ (分別對應) | - |
8 | == != | 用于關系運算符 ==(等于)和 !=(不等于) (分別對應) | - |
9 | & | 按位與 | - |
10 | ^ | 按位異或(獨占或) | - |
11 | | | 按位或(包含或) | - |
12 | && | 邏輯與 | - |
13 | || | 邏輯或 | - |
14 | ?: | 條件運算符[注釋3] | 從右到左 |
15[注釋4] | = += -= *= /= %= <<= >>= &= ^= |= | 簡單賦值 加法賦值、減法賦值 乘法賦值、除法賦值、取余賦值 按位左移賦值、按位右移賦值 按位與賦值、按位異或賦值、按位或賦值 | - |
16 | , | 逗號 | 從左到右 |
三、表達式求值
3.1 整型提升
C語言中整型算術運算總是至少以默認整型類型的精度來進行的。
為了獲得這個精度,表達式中的字符和短整型操作數在使用之前被轉換為普通整型,這種轉換稱為整型提升
整型提升的意義:
表達式中的整型運算要在CPU的響應運算器件內執行,CPU整型運算器(ALU)的操作數的字節長度一般就是int的字節長度,同時也是CPU的通用寄存器的長度。
因此,即使兩個char類型的相加,在CPU執行時實際上也要先轉換為CPU內整型操作數的標準長度。
通用CPU(general-purpose CPU)是難以直接實現兩個8比特字節直接相加運算(雖然極其指令中可能有這種字節相加指令)。所以,表達式中各種長度可能小于int長度的整型值,都必須先轉換為int或unsigned int,然后才能送入CPU去執行運算。
如何進行整型提升呢?
- 有符號整數提升是按照變量的數據類型的符號位來提升的
- 無符號整數提升,高位補0
多說無益,拿例子來看:
看到這串代碼,你的第一反應c的值是多少呢?
會不會是140呢?
哈哈我既然拿出來了,它當然就沒有那么簡單了,打印出的值是-116
首先排除140,因為char類型的取值范圍是:-128-127,他根本就存不下140,這里就要進行整型提升的操作:
首先這里20是int類型,4個字節要放到char里面去,char只有一個字節的空間,所以只能有8個比特位,這就需要截斷一部分了,這里是截斷高位,保留低位,這里a和b相加的時候要發生整型提升
在我們當前的msvc編譯器下,char就是所謂的signed char,所以整型提升就按第一個走
過程展示
因為這里%d注釋處的原因,加和起來的c也需要整型提升
3.2 算數轉化
如果某個操作符的各個操作數屬于不同的類型,那么除非其中一個操作數轉換為另一個操作數的類型,否則操作無法進行,下面的圖中的層次體系就稱為尋常算術轉換。
編譯器會根據內容自動轉換數據類型,是由小的類型向大的類型轉化,就如箭頭所指方向
比如這里整型100+浮點型55.5,編譯器就會自動將整型100轉換為浮點型100,再進行相加和。
總結
雖然在這里已經有了操作符的優先級和結合性,但如果我們寫代碼的時候表達式過于復雜,計算結果的路徑不唯一,一串代碼同一函數多次調用,任有可能寫出問題代碼(因為調用的先后次序無從得知,不同編譯器下的計算次序可能不同),所以在平時寫代碼的時候,表達式還是建議多次拆分,簡單化更好。
這次決定把文章的重點內容設為標題看一看效果,因為前幾篇文章流量不太好,有點小傷心,希望喜歡作者文章的靚仔靚女多多點贊支持一下,你們的支持就是我最大的動力!