網站首頁 編程語言 正文
一、C語言關鍵字詳解
1. sizeof
???????sizeof相信大家并不陌生,其作用就是計算變量所占用的內存空間大小。sizeof的用法看著和函數很相似,但sizeof的真實身份確是:sizeof既是關鍵字,也是運算符,但不是函數! 這點需要大家牢記。還有非常重要的一點就是 sizeof中的表示式編譯器不會進行編譯處理,其原因就是sizeof是在編譯的時候執行的,而C語言的運算符計算是在程序運行的時候執行的,故 sizeof里面的表達式是不會被執行的。下面以一個實際的程序來為大家演示一下。
源代碼:
#include <stdio.h>
int main()
{
int a = 3, b = 0;
b = sizeof(a++);
printf("a = %d, b = %d\n", a, b);
return 0;
}
運行結果:
a = 3, b = 4
???????看上面的程序就知道,雖然在sizeof表達式中變量 a 進行了自增1操作,但是 ++ 運算符是在程序執行的時候運行的,而sizeof表達式是在程序編譯的時候運行的,所以 ++ 操作并不會被執行。
2. const
???????const關鍵字的作用就是將變量常量化。大家都知道變量是可以進行隨意賦值的,但是常量不可以。而被const修飾的變量是不能夠被賦值的,盡管如此,但是我們依舊有方法可以將其進行改變,看下面例子:
源代碼:
#include <stdio.h>
int main()
{
const int a = 3;
//a = 4; //程序報錯,因為變量a被const修飾成只讀的變量了。
int *p = &a;
*p = 8;
printf("a = %d\n", a);
return 0;
}
運行結果:
a = 8
???????上面講到const修飾的變量是不能夠被賦值的,因此程序中注釋的那一行會報錯,這是合理的。在下面我們定義了一個指針指向變量 a ,并且通過指針的方式來改變變量 a 地址里面的內容,這樣是合理的。我們可以這樣來理解,首先定義一個變量 a , 那么這個變量 a 是具有可讀可寫屬性的,用 const 對 a 進行修飾,可以理解成 const 去掉了變量 a 的寫屬性,只保留了讀屬性,所以不能再對 a 進行賦值了。接著我們定義了一個指針變量指向 a 的地址,這個新定義的指針變量沒有被 const 修飾,所以具備可讀可寫屬性,然后通過指針變量來對地址里面的值進行操作,相當于是間接改變了變量 a 里面的內容。所以const的作用可以簡述成一句話,那就是 const修飾誰,誰不能被直接賦值,但是可以通過間接的方式來改變其內容。
3. static
static修飾的變量會存儲在靜態存儲區,靜態存儲區默認值是0。
static的三個作用:
- static修飾的局部變量只會被初始化一次。
- static修飾的全局變量只能在本文件中被使用,不能在其他文件中使用。
- static修飾的全局函數只能在本文件中被使用,不能在其他文件中使用。
作用1將在下面的程序示例為大家演示,作用2和作用3將結合 extern 關鍵字為大家演示。
源代碼:
#include <stdio.h>
void func()
{
static int a = 2;
int b = 2;
a++;
b++;
printf("a = %d, b = %d\n", a, b);
}
int main()
{
int i = 0;
for(i = 1; i <= 2; i++){
func();
}
return 0;
}
運行結果:
a = 3, b = 3
a = 4, b = 3?
???????上面程序中,就是調用了兩次 func() 函數,func() 函數的功能就是定義兩個變量,并且執行加1操作,然后打印輸出。變量 a 因為被 static 修飾,所以 a 被存儲在靜態存儲區,靜態存儲區中的內容是要等程序結束完才會被釋放。并且 a 只會在程序第一次進來的時候被初始化一次,后續再進來的時候不會再執行初始化操作,且保留函數上一次退出的時候的值。而變量 b 沒有被 static 修飾,所以存儲在棧區,棧區中的內容會在該函數結束的時候被回收,所以每次執行func() 函數變量 b 都會被重新賦值。
4. extern
???????extern一般只有在多文件編程的時候才會被用到,是用來修飾變量或函數的,并且告訴編譯器,該變量或函數是在別的文件中被定義的,下面用一個實例來進行具體說明:
文件1源代碼:
int a = 10;
int add(int a, int b)
{
return a+b;
}
文件2源代碼:
#include <stdio.h>
extern int a;
extern int add(int a, int b);
int main()
{
printf("a = %d, sum = %d\n", a, add(10, 20));
}
文件1和文件2同時運行結果:
a = 10, sum = 30
???????上面程序中在文件2中調用了文件1的變量和函數,因為變量和函數都是在文件1中定義的,所以我們想要引用到文件1中的變量或函數時就必須要用extern進行聲明,否則就會報錯。
???????假設我們在文件1中將變量和函數用static進行修飾,文件2不變。
改變后的文件1源代碼
static int a = 10;
static int add(int a, int b)
{
return a+b;
}
???????這個時候再同時運行文件1和文件2就會報錯。報錯的原因就是在文件2中找不到變量和函數。其原因就是被static修飾的變量或函數只能在該文件中使用。
5. volatile
???????volatile的作用一句話概述的話就是防止編譯器優化。 cpu讀取變量的時候是先從內存中讀取到寄存器,再從寄存器中讀取變量的值,但是可能在一些情況下編譯器認為某些變量的值沒有發生變化,因此就省略了從內存中讀取變量的操作,直接從寄存器中讀取。但是這些值可能會被外部環境所改變,比如說是在中斷或者別的線程里面改變,這個時候如果編譯器沒有及時更新變量在寄存器中的值就會導致讀取錯誤。但如果將這個變量用volatile關鍵字修飾的話就可以保證cpu在讀取變量的時候一定會從內存中讀取到寄存器,這樣就可以保證讀取變量的值不出錯。
6. typedef
???????typedef的作用就是為已有類型取別名,注意typedef只是取別名,而不是創造出一個新的類型。
源代碼:
#include <stdio.h>
int main()
{
typedef int u32;
u32 a = 10, b = 20; //等價于 int a = 10, b = 20;
printf("a+b = %d\n", a+b);
return 0;
}
運行結果:
a+b = 30
???????上面代碼中使用 typedef 將 int 類型取名為 u32,對于編譯器而言,只要是看到 u32 都會默認將其轉換為 int 。取別名主要是方便我們來寫和閱讀代碼,而并不會說是創造了新類型。
7. enum
???????enum就是枚舉類型,因為我們有的變量可能取值范圍就是那么幾個值,不會出現別的值。像這種情況下我們就最好使用枚舉類型,注意的是枚舉的值默認是從0開始的,后面的值以此增加,如果我們對枚舉變量中某個值進行手動賦值,那么被手動賦值的后面那個值會在此基礎上加1。舉個實例為大家具體講解:
源代碼:
#include <stdio.h>
/*0, 1, 2, 3, 4, 5, 6*/
enum weekday{Monday, Tuesday, Wednesday, Thursday, Friday, Staurday, Sunday};
/*0, 1, 5, 6, 7*/
enum num{ONE, TWO, THREE=5, FOUR, FIVE};
int main()
{
enum weekday day = 3;
day = Thursday;
enum num number = FIVE;
printf("day = %d, number = %d\n", day, number);
return 0;
}
運行結果:
day = 3, number = 7
8. continue
continue用法兩大注意項:
(1)continue只能用在循環體當中。
(2)continue的作用是結束本次循環,進入到下一次循環。
源代碼:
#include <stdio.h>
int main()
{
int i;
int a[5] = {12, 13, 5, 11, 10};
for(i = 0; i < 5; i++){
if(a[i] < 10){
continue;
}
printf("a[%d] = %d\n", i, a[i]);
}
return 0;
}
運行結果:
a[0] = 12
a[1] = 13
a[3] = 11
a[4] = 10
???????從上面程序可以看出,a[2] 的結果是 5,所以結束本次循環進入下次循環,所以當 i 的值為 2 的時候不會輸出打印。
9. break
break用法兩大注意項:
(1)break只能用于循環體或 switch…case 語句中。
(2)break的作用是跳出本循環體外,值得注意的是如果有多層循環嵌套的話,break是只能跳出它所在的那一層循環體。
源代碼:
#include <stdio.h>
int main()
{
int i;
int a[5] = {12, 13, 5, 11, 10};
for(i = 0; i < 5; i++){
if(a[i] < 10){
break;
}
printf("a[%d] = %d\n", i, a[i]);
}
return 0;
}
運行結果:
a[0] = 12
a[1] = 13
???????從上面程序看,a[2] 的結果是 5,break就直接跳出了循環體,然后程序就結束運行了。因此從這里就能夠看出continue關鍵字和break關鍵字最大的區別了,這兩個關鍵字的區別也是??嫉?,大家可以好好熟悉。
原文鏈接:https://blog.csdn.net/liung_/article/details/123015109
相關推薦
- 2022-01-26 maatwebsite/Excel 導入 iconv (): Detected an illegal
- 2022-09-20 Python處理時間戳和時間計算等的腳本分享_python
- 2022-05-17 Spring Cloud OpenFeign源碼解析
- 2022-12-22 C++模擬實現STL容器vector的示例代碼_C 語言
- 2023-01-18 GO實現跳躍表的示例詳解_Golang
- 2023-01-02 正確在Flutter中添加webview實現詳解_Android
- 2024-02-17 通過springMVC統一設置localhost的時間格式
- 2022-03-30 用C語言畫一個圓_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支