Misra 標準要求函式的單點退出,但我有以下“轉換”代碼
typedef enum { CASE_A, CASE_B, CASE_C } my_enum_t;
int my_conv_funct(my_enum_t value)
{
switch(value)
{
case CASE_A:
return 0;
case CASE_B:
return 1;
case CASE_C:
return 2;
default:
break;
}
log_error("ERROR!!!!!");
assert(1==0);
}
這是有效的嗎?我需要將其轉換為單個回傳函式嗎?處理默認情況的最佳方法是什么?
這在理論上創建了一個無法訪問的代碼(錯誤是警告,以防在列舉中添加一個值而不添加相應的案例)
順便說一句,這是一個嵌入式系統,這些斷言會產生問題嗎?
謝謝,尼克
uj5u.com熱心網友回復:
很簡單:
int my_conv_funct(my_enum_t value)
{
int result = -1;
switch(value)
{
case CASE_A:
result = 0;
break;
case CASE_B:
result = 1;
break;
case CASE_C:
result = 2;
break;
default:
break;
}
if(result == -1)
{
log_error("ERROR!!!!!");
assert(1==0);
}
return result;
}
uj5u.com熱心網友回復:
這是有效的嗎?
它不符合您描述的 MISRA 規則。
我需要將其轉換為單個回傳函式嗎?
為了遵守 MISRA 規則,是的。
處理默認情況的最佳方法是什么?
我們無法判斷什么對您的特定情況和使用來說是“最好的”。
順便說一句,這是一個嵌入式系統,這些斷言會產生問題嗎?
斷言的想法是它可以幫助您在開發程序中發現編程錯誤,但是(原則上)它會通過打算在生產中使用的代碼中的構建選項被禁用。如果遵循該模型,那么斷言本身可能不會產生問題,但函式在默認情況下(如果斷言被禁用)不回傳值的事實會產生問題。如果程式必須在執行默認情況時終止,則它應該呼叫abort(),或其他具有該效果的函式。否則,它應該在默認情況下回傳一個合理的值。
我可能會更像這樣撰寫函式:
int my_conv_funct(my_enum_t value)
{
switch(value)
{
case CASE_A:
case CASE_B:
case CASE_C:
break;
default:
log_error("ERROR!!!!!");
assert(0);
break;
}
return value;
}
現在函式只有一個退出點,如果它完全回傳,則回傳它的引數(隱式轉換為 type int)。
uj5u.com熱心網友回復:
首先請檢查這個答案:計算函式回傳值的最佳實踐。MISRA-C 規則是建議性的,我建議對其進行永久偏離。我個人用以下規則替換它:
“應該避免在一個函式中使用多個 return 陳述句,除非它們使代碼更具可讀性/可維護性。”
避免從嵌套復雜代碼中的多個位置回傳的基本原理是合理的,但在干凈和可讀的函式中則不然。
不過,在您的特定情況下,我可能會像這樣重寫函式(符合 MISRA 而不忽略規則):
uint32_t my_conv_funct (my_enum_t value)
{
uint32_t result;
switch(value)
{
case CASE_A: result = 0; break;
case CASE_B: result = 1; break;
case CASE_C: result = 2; break;
default:
{
// error handling here
}
}
return result;
}
或者(偏離規則):
uint32_t my_conv_funct (my_enum_t value)
{
static const uint32_t lut[] = { CASE_A, CASE_B, CASE_C };
for(size_t i=0; i<sizeof lut/sizeof *lut; i )
{
if(lut[i] == value)
{
return i;
}
}
/* error handling */
return some_error_code;
}
這假設專案的數量不大,在這種情況下,二進制搜索可能效率更低。
這反過來假設列舉常量不對應于 0、1 和 2,在這種情況下,整個函式是無意義的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/341532.html
