求字節數運算符
用於計算數據類型所占的字節數(sizeof)。
一、sizeof的概念
sizeof是c語言的一種單目操作符,如c語言的其他操作符++、--等。並且它並不是一個函數,sizeof的操作符以字節的形式給出了操作數的儲存大小(操作數可以是一個表達式或括號里的類型名)並其儲存的大小有操作數的類型決定,和本身無關系。
二、sizeof的使用方法
1.用於數據類型
sizeof的使用形式:sizeof(char)注意數據類型必須用括號。
2.用於變量
sizeof使用形式:sizeof(a)或者 sizeof a都是正確的形式,但是大多的人都會帶上括號。
* sizeof的操作符不能用於函數類型,不完全類型。不完全類型是指具有未知儲存大小的數據類型,如未知儲存大小的數組類型、未知內容的結構或聯合類void類型、、、、
三、主要用途
1.求基本類型和復合類型所占的內存字節數
如:sizeof(int)、sizeof(int *)
2.求某個變量或者常量所占的內存字節數
如:int i;
sizeof(i)
sizeof(5)
sizeof(5L)
3.求表達式所占的內存字節數,但是不執行括號里面的表達式
如:size(i++), i的值不變
4.求靜態數組所占的內存字節數,這里的數組不能是指針,就是說所定義的數組和所用的sizeof的地方是同一個函數
如:int a[10]
5.求函數返回值類型所占字節數,但是不調用函數
誤區:
1.sizeof是運算符不是函數
2.用sizeof求到的是一個unsigned int 的值
3.當數組是指針的時候求到的是指針所占的內存字節數
4.不可以求void類型所占內存字節數,可以求void類型指針所占內存字節數
sizeof(void)不可以
sizeof(void *)可以
四、特點
1、sizeof是運算符,不是函數。sizeof以byte為單位返回操作數的大小。
2、sizeof不能求得 void 類型的長度。
3、sizeof能求得 void * 類型的長度。
4、sizeof能求得靜態分配內存的數組的長度。
5、sizeof不能求得動態分配的內存的大小!
6、sizeof不能對不完整的數組求長度!
7、當表達式作為sizeof的操作數時,它返回表達式的計算結果的類型大小,但是它不對表達式求值!
8、sizeof可以對函數調用求大小,並且求得的大小等於返回類型的大小,但是不執行函數體。
9、sizeof求得的結構體(及其對象)的大小並不等於各個數據成員對象的大小之和!
10、sizeof不能用於求結構體的位域成員的大小,但是可以求得包含位域成員的結構體的大小!
關於運算符sizeof特點的詳細解釋,請參考https://blog.csdn.net/w57w57w57/article/details/6626840
如果你正在學習編程遇到瓶頸,感到迷茫,困惑,值得加入我的【C語言C++學習企鵝圈子】
學習交流,技術探討,面試指導,簡歷修改...還有超多源碼素材等學習資料,零基礎的視頻等着你!
特殊運算符
有括號(),下標[],成員(→,.)等幾種。

一、下標運算符 []
借助於下標運算符 [](subscript operator),可以獲取數組中單獨的元素。下標運算符需要兩個操作數。在最簡單的情況下,一個操作數是一個數組名稱,而另一個操作數是一個整數。
在下面的示例中,假設 myarray 是一個數組的名稱,並且 i 是一個整數類型的變量。表達式 myarray[i] 指定該數組內的第 i 號元素,數組中第 1 個元素的編號為 0,換句話說,第 i 號元素是數組中第 i+1 個元素。
運算符 [] 的左操作數不一定需要是數組名稱。一個操作數必須是一個指針類型表達式(例如,數組名稱就是這類表達式的一種),同時,另一個操作數必須是整數。表達式 x[y] 等效於(*((x)+(y)))。下面的示例使用下標運算符初始化一個動態生成的數組。
#include <stdlib.h>
#define ARRAY_SIZE 100
/* ... */
double *pArray = NULL; int i = 0;
pArray = malloc( ARRAY_SIZE * sizeof(double) ); // 生成這個數組
if ( pArray != NULL ) {
for ( i = 0; i < ARRAY_SIZE; ++i ) // 對數組進行初始化
pArray[i] = (double)rand()/RAND_MAX;
/* ... */
}
在該示例中,循環體內的表達式 pArray[i] 等效於 *(pArray+i)。i[pArray] 也是正確的,該表示方式也會生成相同的數組元素。
二、成員(→,.)
二元運算符 . 和 -> 常常被稱為點運算符(dot operator)和箭頭運算符(arrow operator),借助於這兩個運算符,可以選擇結構或聯合中的成員。
例 1 展示了點運算符的左操作數必須是一個結構或者一個聯合,而右操作數必須是該類型(結構或聯合)成員的名字。
struct Article { long number; // 物品編號
char name[32]; // 物品名字
long price; // 物品單價(精確到美分)
/* ... */
};
struct Article sw = { 102030L, "Heroes", 5995L };
sw.price = 4995L; // 將價格改為49.95
點運算結果的類型,與所選擇成員的類型是一樣的。如果左操作數是一個左值,那么該運算也會產生左值。如果左操作數的類型有限定符(例如被聲明為 const),那么結果類型也有該限定符。
點運算符的左操作數並非一定是左值,如下例所示:
struct Article getArticle();// 函數原型
printf("name: %s\n",getArticle().name);
函數 getArticle()返回一個 struct Article 類型的對象。按此結果,getArticle().name 是一個有效的表達式,但不是一個左值,因為函數的返回值不是一個左值。
運算符 -> 也可用於選擇結構或聯合的成員,但是箭頭運算符的左操作數必須是一個指針,它指向一個結構或聯合類型。右操作數是該結構或聯合成員的名字。例 2 展示了運算符->的用法,同樣使用例 1 所定義的結構 Article。
【例2】
struct Article *pArticle = &sw, // 一個指向struct Article的指針
const *pcArticle = &sw; // 一個指向struct Article的只讀指針
++(pArticle->number); // 增加編號
if ( pcArticle->number == 102031L ) // 正確:獲取只讀指針
pcArticle->price += 50; // 錯誤:不能使用限定符const的指針來修改對象
箭頭運算符的結果總是一個左值。它具有被選取成員的類型,也同樣包括了其指針操作數的任何類型限定符。在例 2 中,pcArticle 是一個指向 const struct Article 的指針。其結果是,表達式 pcArticle->price 是一個常量。
包含箭頭運算符的任何表達式,都可以利用點運算符進行重寫,做法是先將指針解參考,然后使用點運算符:表達式 p->m 等效於(*p).m;相反地,如果 x 是左值的話,表達式 x.m 等效於(&x)->m。
和運算符 [] 一樣,點運算符 . 和箭頭運算符 -> 都具有最高的優先級,並且組合方式都是從左到右。因此,表達式 ++p->m 等同於 ++(p->m),表達式 p->m++ 等同於(p->m)++。
然而,表達式(*p).m 中的括號是有必要的,因為復引用運算符 * 的優先級比較低。表達式 *p.m 等效於 *(p.m),這種等效僅當在成員 m 是指針時才有意義。
我們通過結合下標運算符、點運算符和箭頭運算符,對一個元素為結構的數組進行操作,來總結本文講述的問題:
struct Article arrArticle[10]; // 一個具有10個元素的數組
// 每個元素為結構類型
arrArticle[2].price = 990L; // 設置數組元素arrArticle[2]的成員price
arrArticle->number = 10100L; // 設置數組元素arrArticle[0]的成員number
一個數組名稱,例如本例中的 arrArticle,是一個指向第一個數組元素的常量指針。所以 arrArticle->number 指向第一個數組元素的成員 number。簡單地說,對於任一的索引值 i,下面 3 個表達式是等價的:
arrArticle[i].number
(arrArticle+i)->number
(*(arrArticle+i)).number
它們都指向數組中索引值為 i 的元素的成員 number。
今天就分享到這里啦,希望對大家學習有所幫助!
