網(wǎng)站制作的公司哪個好南寧seo營銷推廣
文章目錄
- Rules
- 8.4 字符集和詞匯約定(Character sets and lexical conventions)
- Rule 4.1 八進制和十六進制轉(zhuǎn)譯序列應(yīng)有明確的終止識別標(biāo)識
- Rule 4.2 禁止使用三字母詞(trigraphs)
- 8.5 標(biāo)識符(Identifiers)
- Rule 5.1 外部標(biāo)識符不得重名
- Rule 5.2 同范圍和命名空間內(nèi)的標(biāo)識符不得重名
- Rule 5.3 內(nèi)部聲明的標(biāo)識符不得隱藏外部聲明的標(biāo)識符
- Rule 5.4 宏標(biāo)識符不得重名
- Rule 5.5 宏標(biāo)識符與其他標(biāo)識符不得重名
- Rule 5.6 typedef 名稱應(yīng)是唯一標(biāo)識符
- Rule 5.7 標(biāo)簽(tag)名稱應(yīng)是唯一標(biāo)識符
- 全局(external linkage)對象和函數(shù)的標(biāo)識符應(yīng)是唯一的
- Rule 5.9 局部全局(internal linkage)對象和函數(shù)的標(biāo)識符應(yīng)是唯一的
- 8.6 類型(Types)
- Rule 6.1 位域(位帶)僅允許使用適當(dāng)?shù)念愋蛠砺暶?位域成員類型限制)
- Rule 6.2 單比特(single-bit)位域成員不可聲明為有符號類型
- 8.7 字符和常量(Literals and constants)
- Rule 7.1 禁止使用八進制常數(shù)
- Rule 7.2 后綴“u”或“U”應(yīng)使用于所有無符號的整數(shù)常量
- Rule 7.3 小寫字符“l(fā)”不得作為常量的后綴使用(僅可使用“L”)
- Rule 7.4除非對象的類型為“指向 const char 的指針”,否則不得將字符串常量賦值給該對象
Rules
8.4 字符集和詞匯約定(Character sets and lexical conventions)
Rule 4.1 八進制和十六進制轉(zhuǎn)譯序列應(yīng)有明確的終止識別標(biāo)識
等級:必要
分析:可判定,單一編譯單元
適用:C90,C99
展開:八進制或十六進制轉(zhuǎn)義序列應(yīng)通過以下任一方式來標(biāo)識其已終止:
?另一個轉(zhuǎn)義序列的開始,或
?字符常量的結(jié)尾或字符串的結(jié)尾
原理:如果十進制或十六進制轉(zhuǎn)義序列后面跟著其他字符,可能會造成混淆。例如,字符常量’\x1f’由單個字符組成,而字符常量’\x1g’由兩個字符’\x1’和’g’組成。將多字符常量表示為整數(shù)的方式是由實現(xiàn)定義的。
如果給字符常量或字符串文字中的每個八進制或十六進制轉(zhuǎn)義序列增加顯示的終止標(biāo)識,則可以減少混淆的可能性。
示例:在此示例中,由 s1,s2 和 s3 指向的每個字符串都等效于字符串“Ag”
const char *s1 = "\x41g"; /* Non-compliant */
const char *s2 = "\x41" "g"; /* Compliant - terminated by end of literal */
const char *s3 = "\x41\x67"; /* Compliant - terminated by another escape */
int c1 = '\141t'; /* Non-compliant */
int c2 = '\141\t'; /* Compliant - terminated by another escape */
Rule 4.2 禁止使用三字母詞(trigraphs)
等級:建議
分析:可判定,單一編譯單元
適用:C90,C99
原理:三字母詞(或叫三聯(lián)符序列)由兩個問號起始,后跟一個特定字符組成。
注意:復(fù)合字母(“<:” “:>” “<%” “%>” “%:” “%:%:”)是被允許的,因為它們只是標(biāo)記符。
示例:比如字符串
"(Date should be in the form ??-??-??)"
會被編譯器解析為
"(Date should be in the form ~~]"
8.5 標(biāo)識符(Identifiers)
Rule 5.1 外部標(biāo)識符不得重名
等級:必要
分析:可判定,系統(tǒng)范圍
適用:C90,C99
展開:本準(zhǔn)則要求不同的外部標(biāo)識符在實現(xiàn)的有效范圍內(nèi)的字符是不同的。
“不重名”取決于實現(xiàn)和所使用的 C 語言版本:
?在 C90 中,最小有效字符范圍是前 6 個字符,且不區(qū)分大小寫;
?在 C99 中,最小有效字符范圍是前 31 個字符,而其通用字符和擴展字符的有效范圍是 6 到 10 個字符
實際上,許多實際的使用環(huán)境(編譯環(huán)境)提供了更大的限制。 例如,通常 C90 中的外部標(biāo)識符區(qū)分大小寫,并且至少前 31 個字符有意義。
原理:如果兩個標(biāo)識符僅在非有效字符上不同,則實際行為無法確定。
如果考慮到可移植性,則應(yīng)謹(jǐn)慎使用“標(biāo)準(zhǔn)”中指定的最低限制來應(yīng)用此規(guī)則。
長標(biāo)識符可能會損害代碼的可讀性。 盡管許多自動代碼生成系統(tǒng)生成的標(biāo)識符很長,但是有一個很好的論據(jù)可以將標(biāo)識符長度保持在此限制之下。
注意:在C99中,如果擴展源字符出現(xiàn)在外部標(biāo)識符中,并且該字符沒有對應(yīng)的通用字符,則標(biāo)準(zhǔn)不會指定它占用多少字符。
示例:在下面的示例中,所有定義都出現(xiàn)在同一個編譯單元中。所討論的實現(xiàn)在外部標(biāo)識符中支持31個區(qū)分大小寫的字符。
/* 1234567890123456789012345678901********* Characters */
int32_t engine_exhaust_gas_temperature_raw;
int32_t engine_exhaust_gas_temperature_scaled; /* Non-compliant */
/* 1234567890123456789012345678901********* Characters */
int32_t engine_exhaust_gas_temp_raw;
int32_t engine_exhaust_gas_temp_scaled; /* Compliant */
超過32個字符后的變量不同,是違法規(guī)則的。
在以下違規(guī)示例中,該實現(xiàn)在外部標(biāo)識符中支持 6 個不區(qū)分大小寫的字符。 兩個編譯單元中的標(biāo)識符不同,但在主要特征上并沒有區(qū)別。
/* file1.c */
int32_t abc = 0;
/* file2.c */
int32_t ABC = 0;
不應(yīng)存在大小寫可能一樣的變量,或者函數(shù),這樣編譯的時候可能會報錯。
Rule 5.2 同范圍和命名空間內(nèi)的標(biāo)識符不得重名
等級:必要
分析:可判定,單一編譯單元
適用:C90,C99
展開:如果兩個標(biāo)識符都是外部標(biāo)識符,則本準(zhǔn)則不適用,因為此情況適用于 Rule 5.1。
如果每個標(biāo)識符都是宏標(biāo)識符,則本準(zhǔn)則不適用,因為這種情況已被 Rule 5.4 和 Rule 5.5 涵蓋。
“不重名”的定義取決于實現(xiàn)和所使用的 C 語言版本:
?在 C90 中,最低要求是前 31 個字符有效
?在 C99 中,最低要求是前 63 個字符有效,通用字符或擴展源字符視為一個字符。
原理:如果兩個標(biāo)識符僅在非有效字符上不同,則實際行為無法確定。
如果考慮到可移植性,則應(yīng)謹(jǐn)慎使用“標(biāo)準(zhǔn)”中指定的最低限制來應(yīng)用此規(guī)則。
長標(biāo)識符可能會損害代碼的可讀性。 盡管許多自動代碼生成系統(tǒng)生成的標(biāo)識符很長,但是有一個很好的論據(jù)可以將標(biāo)識符長度保持在此限制之下。
示例:在下面的示例中,所討論的實現(xiàn)為:在不具有全局屬性的標(biāo)識符中支持 31 個區(qū)分大小寫的字符。
/* 1234567890123456789012345678901********* Characters */
extern int32_t engine_exhaust_gas_temperature_raw;
static int32_t engine_exhaust_gas_temperature_scaled; /* Non-compliant */
void f ( void )
{/* 1234567890123456789012345678901********* Characters */int32_t engine_exhaust_gas_temperature_local; /* Compliant */
}
/* 1234567890123456789012345678901********* Characters */
static int32_t engine_exhaust_gas_temp_raw;
static int32_t engine_exhaust_gas_temp_scaled; /* Compliant */
跟5.1類似,這里指的是局部或靜態(tài)變量
Rule 5.3 內(nèi)部聲明的標(biāo)識符不得隱藏外部聲明的標(biāo)識符
等級:必要
分析:可判定,單一編譯單元
適用:C90,C99
展開:內(nèi)部范圍聲明的標(biāo)識符應(yīng)與外部范圍聲明的標(biāo)識符不重名。
“不重名”的定義取決于實現(xiàn)和所使用的 C 語言版本:
?在 C90 中,最低要求是前 31 個字符有效
?在 C99 中,最低要求是前 63 個字符有效,通用字符或擴展源字符視為一個字符。
原理:如果在內(nèi)部作用域中聲明一個標(biāo)識符,與在外部作用域中已經(jīng)存在的標(biāo)識符重名,則最內(nèi)部的聲明將“隱藏”外部的聲明。 這可能會導(dǎo)致開發(fā)人員混亂。
注意:在一個名稱空間中聲明的標(biāo)識符不會隱藏在另一個名稱空間中聲明的標(biāo)識符
術(shù)語“內(nèi)部作用域”和“外部作用域”定義如下:
?具有文件作用域的標(biāo)識符可以被認(rèn)為具有最外層作用域;
?文件內(nèi)模塊間可識別的范圍,作用域較小,相對最大范圍,視為內(nèi)部作用域;
?連續(xù)的嵌套塊,引入更多的內(nèi)部作用域。
示例:
void fn1 ( void )
{int16_t i; /* 定義變量 "i" */{int16_t i; /* 違規(guī) - 會隱藏前面定義的 "i" */i = 3; /* 這里的 "i" 是指前面哪一個, 會產(chǎn)生混淆 */}
}
struct astruct
{int16_t m;
};
extern void g ( struct astruct *p );
int16_t xyz = 0; /* 定義變量 "xyz" */
void fn2 ( struct astruct xyz ) /* 違規(guī) - 外部定義的 "xyz" 被同名形參隱藏 */
{g ( &xyz );
}
uint16_t speed;
void fn3 ( void )
{typedef float32_t speed; /* 違規(guī) - 類型將變量給隱藏 */
}
Rule 5.4 宏標(biāo)識符不得重名
等級:必要
分析:可判定,單一編譯單元
適用:C90,C99
展開:該規(guī)則要求,當(dāng)定義宏時,其名稱與:
?當(dāng)前定義的其他宏的名稱,和
?參數(shù)的名稱。
“不重名”的定義取決于實現(xiàn)和所使用的 C 語言版本:
?在C90中,最低要求是宏標(biāo)識符的前31個字符是有效的;
?在C99中,最低要求是宏標(biāo)識符的前63個字符是有效的。
在實踐中,實現(xiàn)可能提供更大的限制。該規(guī)則要求宏標(biāo)識符在實現(xiàn)所施加的限制內(nèi)是不同的。
原理:如果兩個宏標(biāo)識符僅非有效字符不同,則其實際實現(xiàn)行為不可預(yù)知。 由于宏參數(shù)僅在其宏擴展期間處于活動狀態(tài),因此一個宏中的參數(shù)與另一宏中的參數(shù)混淆不會有問題
考慮到可移植性,則應(yīng)謹(jǐn)慎使用“標(biāo)準(zhǔn)”中指定的最低限制來應(yīng)用此準(zhǔn)則。
過長的宏標(biāo)識符可能會損害代碼的可讀性。 盡管許多自動代碼生成系統(tǒng)會生成很長的宏標(biāo)識符,但有一個很好的論據(jù)認(rèn)為宏標(biāo)識符的長度應(yīng)遠低于此限制。
注意:在C99中,如果擴展源字符出現(xiàn)在宏名稱中,并且該字符沒有相應(yīng)的通用字符,則標(biāo)準(zhǔn)不會指定它占用多少字符。
示例:在下面的示例中,所討論的實現(xiàn)在宏標(biāo)識符中支持31個重要的區(qū)分大小寫的字符。
/* 1234567890123456789012345678901********* Characters */
#define engine_exhaust_gas_temperature_raw egt_r
#define engine_exhaust_gas_temperature_scaled egt_s /* Non-compliant */
/* 1234567890123456789012345678901********* Characters */
#define engine_exhaust_gas_temp_raw egt_r
#define engine_exhaust_gas_temp_scaled egt_s /* Compliant */
Rule 5.5 宏標(biāo)識符與其他標(biāo)識符不得重名
等級:必要
分析:可判定,單一編譯單元
適用:C90,C99
展開:該規(guī)則要求預(yù)處理前存在的宏的名稱與預(yù)處理后存在的標(biāo)識符不同。它適用于標(biāo)識符,而不考慮其作用域或名稱空間,也適用于已定義的任何宏,而不考慮在聲明標(biāo)識符時定義是否仍然有效。
根據(jù)所使用的C 語言的實現(xiàn)和版本,“不重名”的定義不相同:
?在C90中,最低要求是前31個字符是有效的;
?在C99中,最低要求是前63個字符是有效的,每個通用字符或擴展源字符計數(shù)為單個字符
原理:保持宏名稱和標(biāo)識符不同有助于避免開發(fā)人員混淆
示例:在下面的不兼容示例中,類似函數(shù)的宏Sum的名稱也用作標(biāo)識符。對象Sum的聲明不受宏展開的約束,因為它后面沒有“(”字符。因此,在執(zhí)行了預(yù)處理之后,標(biāo)識符仍然存在。
#define Sum(x, y) ( ( x ) + ( y ) )
int16_t Sum;
下面的示例是兼容的,因為預(yù)處理后沒有標(biāo)識符Sum的實例
#define Sum(x, y) ( ( x ) + ( y ) )
int16_t x = Sum ( 1, 2 );
在下面的示例中,假定有效字符長度為 31 且區(qū)分大小寫。該示例違規(guī),因為宏名稱與標(biāo)識符的前 31 個字符完全相同。
/* 1234567890123456789012345678901********* Characters */
#define low_pressure_turbine_temperature_1 lp_tb_temp_1
static int32_t low_pressure_turbine_temperature_2;
Rule 5.6 typedef 名稱應(yīng)是唯一標(biāo)識符
等級:必要
分析:可判定,系統(tǒng)范圍
適用:C90,C99
展開:類型定義名稱在所有名稱空間和翻譯單元中應(yīng)該是唯一的。只有當(dāng)類型定義在頭文件中并且該頭文件包含在多個源文件中時,該規(guī)則才允許對相同的typedef名稱進行多個聲明。
原理:如果多個 typedef 名稱命名相同而它們實際指代又是不同的函數(shù)、對象或枚舉常量時,開發(fā)人員會被困擾
例外:typedef 名稱可以與和 typedef 相關(guān)聯(lián)的結(jié)構(gòu)、聯(lián)合或枚舉標(biāo)記(tag)名稱相同。
void func ( void )
{{typedef unsigned char u8_t;}{typedef unsigned char u8_t; /* Non-compliant - reuse */}
}
typedef float mass;
void func1 ( void )
{float32_t mass = 0.0f; /* Non-compliant - reuse */
}
typedef struct list
{struct list *next;uint16_t element;
} list; /* Compliant - exception */
typedef struct
{struct chain{struct chain *list;uint16_t element;} s1;uint16_t length;
} chain; /* Non-compliant - tag "chain" not* associated with typedef */
Rule 5.7 標(biāo)簽(tag)名稱應(yīng)是唯一標(biāo)識符
等級:必要
分析:可判定,系統(tǒng)范圍
適用:C90,C99
展開:標(biāo)簽(tag)在所有名稱空間和單位翻譯中應(yīng)是唯一的。
標(biāo)簽(tag)的所有聲明應(yīng)指定相同的類型。
僅當(dāng)在頭文件中聲明標(biāo)簽(tag)并且該頭文件被多個源文件包含時,此準(zhǔn)則才允許使用同一標(biāo)簽(tag) 的多個完整聲明。
與 typedef 名稱相同,這種情況下,所有聲明都是完全相同的,且由于頭文件防止多次包含的舉措,也不會出現(xiàn)多個聲明
原理:重用標(biāo)簽(tag)名稱可能會導(dǎo)致開發(fā)人員混亂。
例外:標(biāo)簽(tag)名稱可能與與其關(guān)聯(lián)的 typedef 名稱相同。
struct stag
{
uint16_t a;
uint16_t b;
};
struct stag a1 = { 0, 0 }; /* 合規(guī) - 與前面的定義一致 */
union stag a2 = { 0, 0 }; /* 違規(guī) - 與聲明的 struct stag 不一致。
* 同時也違背了C99的約束 */
下述的示例也違背了 Rule 5.3:
struct deer
{
uint16_t a;
uint16_t b;
};
void foo ( void )
{
struct deer
{
uint16_t a;
};/* 違規(guī) - 標(biāo)簽 "deer" 重復(fù)使用 */
}
typedef struct coord
{
uint16_t x;
uint16_t y;
} coord;/* 合規(guī) - 符合例外情況 */struct elk
{uint16_t x;
};
struct elk /* 違規(guī) - 同一個標(biāo)簽被聲明為不同的類型* 同時也違背了C99的約束 */
{uint32_t x;
};
全局(external linkage)對象和函數(shù)的標(biāo)識符應(yīng)是唯一的
等級:必要
分析:可判定,系統(tǒng)范圍
適用:C90,C99
展開:用作外部標(biāo)識符的標(biāo)識符不得在任何命名空間或編譯單元中用于任何其他目的,即使它沒有鏈接的對象。
原理:強制標(biāo)識符名稱的唯一性有助于避免混淆。沒有鏈接對象的標(biāo)識符不必是唯一的,因為混淆風(fēng)險很小
示例:下面的示例中,“file1.c”和“file2.c”是同一個項目的一部分。
/* file1.c */
int32_t count; /* "count" 具有全局屬性(全局變量) */
void foo ( void ) /* "foo" 具有全局屬性(全局函數(shù)) */
{int16_t index; /* "index" 無全局屬性(臨時變量) */
}
/* file2.c */
static void foo ( void ) /* 違規(guī) - “ foo”不唯一(在file1.c中有全局屬
* 性的同名函數(shù)) */int16_t count; /* 違規(guī) - "count" 沒有全局屬性, 但與另一文
* 件的有全局屬性的變量重名 */int32_t index; /* 合規(guī) - "index"無全局屬性(臨時變量) */
}
全局變量不能與局部變量名稱一樣,全局函數(shù)不能與局部函數(shù)名稱一致。
Rule 5.9 局部全局(internal linkage)對象和函數(shù)的標(biāo)識符應(yīng)是唯一的
等級:必要
分析:可判定,系統(tǒng)范圍
適用:C90,C99
展開:標(biāo)識符名稱在所有命名空間和編譯單元中都應(yīng)該唯一。任何標(biāo)識符都不應(yīng)與任何其他標(biāo)識符具有相同的名稱,即使該其他標(biāo)識符沒有鏈接的對象也是如此。
原理:強制標(biāo)識符名稱的唯一性有助于避免混淆。
例外:可以在一個以上的轉(zhuǎn)換單元中定義具有局部屬性的內(nèi)聯(lián)函數(shù),條件是所有這些定義都在每個轉(zhuǎn)換單元中包含的同一頭文件中進行。即:定義在頭文件中的內(nèi)聯(lián)函數(shù),不受限制。
示例:下面的示例中,“file1.c”和“file2.c”是同一個項目的一部分。
/* file1.c */
static int32_t count; /* "count" 局部全局屬性 */
static void foo ( void ) /* "foo" 局部全局屬性 */
{int16_t count; /* 違規(guī) - "count" 沒有全局屬性, 但與有局部全
* 局屬性的標(biāo)識符沖突 */int16_t index; /* "index" 無全局屬性 */
}
void bar1 ( void )
{static int16_t count; /* 違規(guī) - "count" 沒有全局屬性, 但與有局部全
* 局屬性的標(biāo)識符沖突 */int16_t index; /* 合規(guī) - "index" 不唯一但它沒有與其沖突的具全
* 局屬性的標(biāo)識符 */foo ( );
}
/* End of file1.c */
/* file2.c */
static int8_t count; /* 違規(guī) - "count" 具有局部全局屬性, 與另一個
* 具有局部全局屬性的標(biāo)識符重復(fù) */
static void foo ( void ) /* 違規(guī) - "foo" 具有局部屬性, 與另一個具有局
* 部屬性的函數(shù)標(biāo)識符重復(fù) */
{int32_t index; /* 合規(guī) - "index" 和 "nbytes" " */int16_t nbytes; /* 不唯一, 但因都不具全局屬性, 因而不沖突 */
}
void bar2 ( void )
{static uint8_t nbytes; /* 合規(guī) - "nbytes" 不唯一, 但它沒有全局屬性,
* 全局屬性與存儲類別無關(guān) */
}
/* End of file2.c */
內(nèi)部鏈接(internal linkage)翻譯為局部全局,即被“static”修飾的全局變量和函數(shù)
靜態(tài)全局變量不能與局部變量/局部靜態(tài)變量同名,也不能與其他文件的靜態(tài)全局變量同名。靜態(tài)全局函數(shù)也不能與其他文件的靜態(tài)全局函數(shù)同名。
8.6 類型(Types)
Rule 6.1 位域(位帶)僅允許使用適當(dāng)?shù)念愋蛠砺暶?位域成員類型限制)
等級:必要
分析:可判定,單一編譯單元
適用:C90,C99
展開:“適當(dāng)?shù)摹蔽挥蝾愋蜑?#xff1a;
?C90: unsigned int或signed int;
?C99:下列之一:
-無符號整型或有符號整型;
-實現(xiàn)允許的另一種顯式有符號或顯式無符號整數(shù)類型;
—_Bool
注意:允許使用typedef來指定適當(dāng)?shù)念愋汀?br /> 原理:使用int是實現(xiàn)定義的,因為int類型的bit-fields字段可以是有符號的也可以是無符號的
在C90中不允許使用enum、short、char或任何其他類型的bit-fields字段,因為該行為是未定義的。
在C99中,實現(xiàn)可以定義在bit-fields字段聲明中允許的其他整數(shù)類型。
示例:以下示例適用于不提供任何其他位域類型的 C90 和 C99 實現(xiàn)。假定 int 類型為 16 位。
typedef unsigned int UINT_16;
struct s {unsigned int b1:2; /* 合規(guī) */int b2:2; /* 違規(guī) - 不允許使用不明確符號的"int" */UINT_16 b3:2; /* 違規(guī) - 不允許使用不明確符號的"int" */signed long b4:2; /* 違規(guī) - 即使 long 和 int 大小相同 */
};
該定義一般用在寄存器定義中,字段的數(shù)據(jù)類型一般都保持一致
Rule 6.2 單比特(single-bit)位域成員不可聲明為有符號類型
等級:必要
分析:可判定,單一編譯單元
適用:C90,C99
原理:根據(jù) C99 標(biāo)準(zhǔn)第 6.2.6.2 節(jié),一個單比特(single-bit)帶符號的位域數(shù)據(jù)具有 1 個符號位和 0 個值位。
在任何整數(shù)表示中,0 個值位都無法指定有意義的值。如果定義會對編程人員產(chǎn)生疑問。
盡管C90標(biāo)準(zhǔn)沒有提供太多關(guān)于類型表示的細(xì)節(jié),但同樣的考慮也適用于C99
注意:此規(guī)則不適用于未命名的位字段,因為它們的值不能被訪問
8.7 字符和常量(Literals and constants)
Rule 7.1 禁止使用八進制常數(shù)
等級:必要
分析:可判定,單一編譯單元
適用:C90,C99
原理:開發(fā)人員編寫帶有前導(dǎo)零的常量時,可能希望它們被解釋為十進制常量。八進制常數(shù)的表述方式:0xx。
注意:此規(guī)則不適用于八進制轉(zhuǎn)義序列,因為使用前導(dǎo)字符\意味著混淆的空間更小
例外:整數(shù)常數(shù)零(寫為“0”)嚴(yán)格來說是八進制常數(shù),但是是本準(zhǔn)則的允許例外。
示例:
extern uint16_t code[ 10 ];
code[ 1 ] = 109; /* Compliant - decimal 109 */
code[ 2 ] = 100; / * Compliant - decimal 100 */
code[ 3 ] = 052; /* Non-Compliant - decimal 42 */
code[ 4 ] = 071; /* Non-Compliant - decimal 57 */
八進制數(shù)一般不會在嵌入式中使用,此處也規(guī)定不能使用
Rule 7.2 后綴“u”或“U”應(yīng)使用于所有無符號的整數(shù)常量
等級:必要
分析:可判定,單一編譯單元
適用:C90,C99
展開:此規(guī)則適用于:
?在預(yù)處理指令#if和#elif的控制表達式中出現(xiàn)的整型常量;
?預(yù)處理后存在的任何其他整型常量。
注:在預(yù)處理過程中,整型常量的類型確定與預(yù)處理后相同,不同之處在于:
?所有有符號整數(shù)類型的行為就像它們是long (C90)或intmax_t (C99);
?所有無符號整數(shù)類型的行為就像它們是unsigned long (C90)或uintmax_t (C99)
原理: 整數(shù)常量的類型是潛在的混淆源,因為它取決于多種因素的復(fù)雜結(jié)合,包括:
?常數(shù)的大小;
?實現(xiàn)的整數(shù)類型的大小;
?任何后綴的存在;
?表示值的基數(shù)(即十進制、八進制或十六進制)。
例如,整數(shù)常數(shù)40000在32位環(huán)境中是signed int類型,但在16位環(huán)境中是signed long類型。值0x8000在16位環(huán)境中是無符號int類型,但在32位環(huán)境中是有符號int類型。
注意:
?任何帶有“U”后綴的值都是unsigned類型;
?小于2^31的無后綴十進制值為有符號類型
?大于或等于2^15的無后綴十進制值為有符號類型號或無符號類型
?對于 C90,大于或等于 2^31的無后綴十進制值可能是有符號或無符號類型
常量的符號應(yīng)該是顯式的。如果常量是無符號類型,則應(yīng)用“U”后綴可以清楚地表明程序員理解該常量是無符號的
注意:該規(guī)則不依賴于使用常量的上下文;可應(yīng)用于常數(shù)的提升和其他轉(zhuǎn)換與確定是否符合此規(guī)則無關(guān)
示例:以下示例假定計算機具有 16 位 int 類型和 32 位 long 類型。它顯示了根據(jù)標(biāo)準(zhǔn)確定的每個整數(shù)常量的
類型。整數(shù)常量 0x8000 不符合標(biāo)準(zhǔn),因為它具有無符號類型,但沒有“ U”后綴。
Rule 7.3 小寫字符“l(fā)”不得作為常量的后綴使用(僅可使用“L”)
等級:必要
分析:可判定,單一編譯單元
適用:C90,C99
原理:在聲明文字時,使用大寫后綴“L”可消除“1”(數(shù)字 1)和“l(fā)”(字母“ el”)之間的潛在歧義。
示例:
const int64_t a = 0L;
const int64_t b = 0l; /* Non-compliant */
const uint64_t c = 0Lu;
const uint64_t d = 0lU; /* Non-compliant */
const uint64_t e = 0ULL;
const uint64_t f = 0Ull; /* Non-compliant */
const int128_t g = 0LL;
const int128_t h = 0ll; /* Non-compliant */
const float128_t m = 1.2L;
const float128_t n = 2.4l; /* Non-compliant */
Rule 7.4除非對象的類型為“指向 const char 的指針”,否則不得將字符串常量賦值給該對象
等級:必要
分析:可判定,單一編譯單元
適用:C90,C99
展開:不得嘗試直接修改字符串常量或?qū)捵址A俊?br />
除非對象的類型為“指向 const char 型數(shù)組的指針”,否則對字符串常量取地址(&運算符修飾)的結(jié)果不得賦值給該對象
同樣的,此限制也適用于寬字符串常量。 除非對象的類型是“指向 const wchar_t 的指針”,否則不得將寬字符串常量賦值給該對象。 除非該對象的類型是“指向 const wchar_t 數(shù)組的指針”,否則對寬字符串常量取地址(&運算符)的結(jié)果不得賦值給該對象。
原理:對字符串常量的修改結(jié)果無法預(yù)知。例如,某些實現(xiàn)可能會將字符串常量存儲在只讀存儲器中,在這種情況下,嘗試修改字符串常量將失敗,并且還可能導(dǎo)致異?;虮罎ⅰ?br />
此規(guī)則可防止誤修改字符串常量。
在 C99 標(biāo)準(zhǔn)中,并未明確指定是否將共享共同結(jié)尾的字符串常量存儲在不同的內(nèi)存位置中。因此,即使嘗試修改字符串常量看起來成功了,也可能會無意中更改了另一個字符串。
示例:下面示例顯示了直接修改字符串常量的嘗試:
"0123456789"[0] = '*'; /* 違規(guī) */
這些示例描述了如何防止間接修改字符串常量。
/* 違規(guī) - s 缺少 const 修飾 */
char *s = "string";
/* 合規(guī) - p 有 const 修飾; 其他限定詞是可接受的 */
const volatile char *p = "string";
extern void f1 ( char *s1 );
extern void f2 ( const char *s2 );
void g ( void )
{f1 ( "string" ); /* 違規(guī) - 形參 s1 缺少 const 修飾 */f2 ( "string" ); /* 合規(guī) */
}
char *name1 ( void )
{return ( "MISRA" ); /* 違規(guī) - 返回類型缺少 const 修飾 */
}
const char *name2 ( void )
{return ( "MISRA" ); /* 合規(guī) */
}
指針對象需要定義為const char,才可以賦值字符串常量