目錄
- 一.const 使用
- 1.const 修飾變數
- 2.const 修飾指標
- 3.const 修飾在函式名前面
- 4.const 修飾在函式名后面
- 5.const 修飾函式引數
- 二.define 使用
- 1.define 定義常量
- 2.define 定義函式
- 3.define 定義多行函式
- 4.define 防止頭檔案重復包含
- 三.const 和 define 區別
- 1.就起作用的階段而言
- 2.就起作用的方式而言
- 3.就存盤方式而言
- 4.從代碼除錯的方便程度而言
- 5.從效率程度而言
- 四.const 優點
- 五.猜你喜歡
零基礎 C/C++ 學習路線推薦 : C/C++ 學習目錄 >> C 語言基礎入門
一.const 使用
const 是 constant 的縮寫,“恒定不變”的意思,被 const 修飾的東西都受到強制保護,可以預防意外的變動,能提高程式的健壯性,所以很多 C++ 程式設計書籍建議:“Use const whenever you need”,
1.const 修飾變數
/******************************************************************************************/
//@Author:猿說編程
//@Blog(個人博客地址): www.codersrc.com
//@File:C語言 const 和 define 區別
//@Time:2021/07/04 08:00
//@Motto:不積跬步無以至千里,不積小流無以成江海,程式人生的精彩需要堅持不懈地積累!
/******************************************************************************************/
#include <stdio.h>
int main() {
const int a = 20 ;
printf("a = %d\n",a);
a = 200 ;
printf("a = %d\n",a);
return 0;
}
/*
輸出:
Compilation Failed
error: assignment of read-only variable 'a'
6 | a = 200 ;
| ~~^~~~~
*/
用 const 定義的變數的值是不允許改變的,即不允許給它重新賦值,即使是賦相同的值也不可以,并且 const 修飾的變數在定義的時候就給它賦初值,否則報錯:
error: uninitialized 'const ' [-fpermissive]
詳細解釋可以直接跳轉:const 修飾變數;
2.const 修飾指標
//以下兩者等價,表示 *p 不可變,*p 表示的是指標變數 p 所指向的記憶體單元里面的內容,此時這個內容不可變;
const int *p
int const *p
//此時 const 修飾的是 p,所以 p 中存放的記憶體單元的地址不可變,而記憶體單元中的內容可變,即 p 的指向不可變,p 所指向的記憶體單元的內容可變;
int * const p
//*p 和 p 都被修飾了,那么 p 中存放的記憶體單元的地址和記憶體單元中的內容都不可變;
const int * const p
詳細解釋可以直接跳轉:const修飾指標;
3.const 修飾在函式名前面
當 const 在函式名前面的時候修飾的是函式回傳值;在函式名后面表示是 C++ 常成員函式,該函式不能修改物件內的任何成員,只能發生讀操作,不能發生寫操作,
const char * GetString(void);
const int GetInt(void);
const float GetFloat(void);
const double GetDdouble(void);
如果給以“指標傳遞”方式的函式回傳值加 const 修飾,那么函式回傳值(即指標)的內容不能被修改,該回傳值只能被賦給加 const 修飾的同型別指標;
const char * GetString(void);
//如下陳述句將出現編譯錯誤:
//char *str = GetString();
//正確的用法是
const char *str = GetString();
如果函式回傳值采用“值傳遞方式”,由于函式會把回傳值復制到外部臨時的存盤單元中,加 const 修飾沒有任何價值,
int GetInt(void);
const int GetInt(void);
以上兩個函式都是都是獨立存在的,并非同一個函式;
4.const 修飾在函式名后面
當 const 在函式名前面的時候修飾的是函式回傳值;在函式名后面表示是 C++ 常成員函式,該函式不能修改物件內的任何成員,只能發生讀操作,不能發生寫操作,
/******************************************************************************************/
//@Author:猿說編程
//@Blog(個人博客地址): www.codersrc.com
//@File:C語言 const 和 define 區別
//@Time:2021/07/04 08:00
//@Motto:不積跬步無以至千里,不積小流無以成江海,程式人生的精彩需要堅持不懈地積累!
/******************************************************************************************/
class People
{
public:
int talk(void);
int eat(void) const; // const 成員函式
private:
int m_age;
};
int People::eat(void) const
{
++m_age; // 編譯錯誤,企圖修改資料成員m_num
talk(); // 編譯錯誤,企圖呼叫非const函式
return m_age;
}
- const 物件只能訪問 const 成員函式,而非 const 物件可以訪問任意的成員函式,包括 const 成員函式;
- const 物件的成員是不可修改的,然而 const 物件通過指標維護的物件卻是可以修改的;
- const 成員函式不可以修改物件的資料,不管物件是否具有 const 性質.它在編譯時,以是否修改成員資料為依據,進行檢查;
- 然而加上 mutable 修飾符的資料成員,對于任何情況下通過任何手段都可修改,自然此時的 const 成員函式是可以修改它的;
5.const 修飾函式引數
如果函式引數采用“指標傳遞”,那么加 const 修飾可以防止意外地改動該指標,起到保護作用,
void StringCopy (char*strDestination, const char *strSource);
其中 strSource 是輸入引數,strDestination 是輸出引數,給 strSource 加上 const 修飾后,如果函式體內的陳述句試圖改動 strSource 的內容,編譯器將指出錯誤,
如果輸入引數采用“值傳遞”,由于函式將自動產生臨時變數用于復制該引數,該輸入引數本來就無需保護,所以不要加 const 修飾,
例如不要將函式 void Func1(int x) 寫成 void Func1(const int x),
如果引數作為輸出引數,不論它是什么資料型別,也不論它采用“指標傳遞”還是“參考傳遞”,都不能加 const 修飾,否則該引數將失去輸出功能(因為有 const 修飾之后,不能改變他的值),
如果引數作為輸入引數,可以防止資料被改變,起到保護作用,增加程式的健壯性;
二.define 使用
1.define 定義常量
C 語言中,可以用 #define 定義一個識別符號來表示一個常量,用 #define 定義識別符號的一般形式為:
#define 識別符號 常量 //注意define最后沒有分號
//例如:
#define MAX_VALUE 100 //定義整型變數MAX_VALUE值為100
#define USER_NAME "huge" //定義字串變數USER_NAME值為"huge"
#define PI 3.1415926 //定義浮點數變數PI值為3.1415926
凡是以 # 開頭的均為預處理指令,預處理又叫預編譯,預編譯不是編譯,而是編譯前的處理,這個操作是在正式編譯之前由系統自動完成的,
2.define 定義函式
//定義常量
#define MAX_VALUE 100 //定義整型變數MAX_VALUE值為100
#define USER_NAME "huge" //定義字串變數USER_NAME值為"huge"
#define PI 3.1415926 //定義浮點數變數PI值為3.1415926
//定義函式
#define MAX(a,b) (a>b)?a:b //取兩個數最大值
#define MIN(a,b) (a<b)?a:b //取兩個數最小值
3.define 定義多行函式
//定義常量
#define MAX_VALUE 100 //定義整型變數MAX_VALUE值為100
#define USER_NAME "huge" //定義字串變數USER_NAME值為"huge"
#define PI 3.1415926 //定義浮點數變數PI值為3.1415926
//定義簡單函式
#define MAX(a,b) (a>b)?a:b //取兩個數最大值
#define MIN(a,b) (a<b)?a:b //取兩個數最小值
//定義復雜多行的函式
#define MACRO(arg1, arg2) do { \
\
stmt1; \
stmt2; \
\
} while(0)
//關鍵是要在每一個換行的時候加上一個 "\ "
使用
define定義一個多行的復雜函式,關鍵是要在每一個換行的時候加上一個\;
4.define 防止頭檔案重復包含
通過 #ifndef / #define 解決頭檔案重復包含
#ifndef __XXX_H__
#define __XXX_H__
int a=1;
#endif
上面的偽代碼如下:
如果(沒有定義宏__XXX_H__)
{
那么直接定義宏__XXX_H__
定義變數a 并且賦值為 1
}
結束程式
- 假如第一次包含時,由于沒有定義宏 __XXX_H,所以做了兩件事,定義宏 __XXX_H,然后定義 int a = 1;
- 假如第二次包含時,由于已經定義宏 __XXX_H__,所以啥都不做;
- 假如第 N 次包含時,由于已經定義宏 __XXX_H__,所以啥都不做;
- 整個程序,無論頭檔案被包含多少次,變數 a 只被定義一次,不會有重復包含重復定義的問題存在!
三.const 和 define 區別
1.就起作用的階段而言
define 是在編譯的預處理階段起作用,而 const 是在 編譯、運行的時候起作用,
2.就起作用的方式而言
define 只是簡單的字串替換,沒有型別檢查,而 const 有對應的資料型別,是要進行判斷的,可以避免一些低級的錯誤,
3.就存盤方式而言
define 只是進行展開,有多少地方使用,就替換多少次,它定義的宏常量在記憶體中有若干個備份; const 定義的只讀變數在程式運行程序中只有一份備份,
4.從代碼除錯的方便程度而言
const 常量可以進行除錯的,define 是不能進行除錯的,因為在預編譯階段就已經替換掉了,
5.從效率程度而言
編譯器通常不為普通 const 常量分配存盤空間,而是將它們保存在符號表中,這使得它成為一個編譯期間的常量,沒有了存盤與讀記憶體的操作,使得它的效率也很高
四.const 優點
- 1.const 常量有資料型別,而宏常量沒有資料型別,編譯器可以對前者進行型別安全檢查,而對后者只進行字符替換,沒有型別安全檢查,并且在字符替換可能會產生意料不到的錯誤,
- 2.有些集成化的除錯工具可以對 const 常量進行除錯,但是不能對宏常量進行除錯,
- 3.const 可節省空間,避免不必要的記憶體分配,提高效率
五.猜你喜歡
- C 語言 陣列下標越界和記憶體溢位區別
- C 語言 指標宣告和定義
- C 語言 指標 p++ / p–
- C 語言 p++/§++/_(p++)/_p++
- C 語言 使用指標遍歷陣列
- C 語言 指標和陣列區別
- C 語言 指標陣列和陣列指標區別
- C 語言 空指標 NULL
- C 語言 void 指標
- C 語言 野指標
- C 語言 函式值傳遞和址傳遞
- C 語言 函式預設引數
- C 語言 函式不定長引數
- C 語言 函式指標
- C 語言 指標函式
- C 語言 回呼函式 callback
- C 語言 typedef
- C 語言 define 定義常量
- C 語言 define 防止頭檔案重復包含
- C 語言 #pragma once
- C 語言 #include <> 與 #include “” 區別
- C 語言 const 修飾變數
- C 語言 const 修飾指標
- C語言 const 修飾函式
- C 語言 const 修飾函式引數
- C 語言 const 和 define 區別
未經允許不得轉載:猿說編程 ? C 語言 const 和 define 區別
本文由博客 - 猿說編程 猿說編程 發布!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/298788.html
標籤:其他
下一篇:java基礎之反射型別Type
