是“enum typename{...};”还是“typedef enum{...}typename;”

本文详细介绍了C语言中枚举类型的两种定义方式及其区别,并提出了作者的个人偏好。同时,通过对比不同定义方式的优缺点,帮助读者理解如何选择最适合项目的枚举类型定义。

一、enum的使用

enum typeName {//定义枚举类型名,可缺省
    EnumerationName1 = 0, //定义枚举元素名
    EnumerationName2,
    ...
}valueName1, valueName2[n];//定义枚举变量,可缺省

enum typeName valueName3;
typedef enum typeName {//定义枚举类型名,typeName 可缺省且不建议加
    EnumerationName1 = 0, //定义枚举元素名
    EnumerationName2,
    ...
}typeName_t;//定义枚举类型名

typeName_t valueName1;
//enum typeName valueName2;//不建议

二、区别

        - 在定义枚举变量时加上enum能一眼就看出该变量为枚举变量,可读性会升高。而且在某些ide中例如vccode中,将鼠标点到结构体中的枚举变量会提示一个" enum typename <name> ",可读性继续增加。

        - 但是这两个用法没区别,都是一个意思

三、个人偏好

        - 在我个人看来,我会更加侧重使用后者,因为前者在定义枚举类型的时候还要加一个enum,真麻烦。

        - 如果是我的建议,我会建议用前者,不要用typedef

<think>我们之前遇到的错误是由于不同版本的Cppcheck中Token对象的属性不同。现在,根据用户提示,我们可以使用`token.function`来检查是否是函数名。这可能是某些版本中提供的属性。因此,我们可以更新我们的方法,优先使用这个属性来识别函数名。 但是,需要注意的是,不同版本的Cppcheck可能有不同的属性。所以,我们仍然需要保持兼容性,即: 1. 如果存在`token.function`属性,并且为True,那么这个token就是函数名。 2. 否则,我们回退到之前的逻辑(即检查是标识符且不是关键字)。 此外,我们之前还遇到了`preprocessor`属性不存在的问题。因此,我们也要确保安全地检查预处理指令。 让我们重新设计函数名识别的逻辑,并更新代码。 另外,为了更准确地识别函数,我们可以利用`token.function`属性(如果存在)。这样,我们就不需要跳过模板和参数列表等复杂步骤,因为该属性已经告诉我们这是一个函数名。 但是,注意:`token.function`可能只在函数定义处被设置为True,而在函数声明(没有函数体)处可能不会设置?我们需要测试。但无论如何,我们可以结合函数体的存在来确认。 改进点: 1. 优先使用`token.function`属性(如果存在)来识别函数名。 2. 对于没有此属性的版本,回退到之前的逻辑(跳过模板、参数列表等)。 同时,我们也要确保其他部分的兼容性(如预处理指令、行号获取等)。 以下是更新后的代码: </think>感谢您的宝贵建议!确实,使用 `token.function` 属性可以更可靠地识别函数名。以下是改进后的完整解决方案,优先使用 `token.function` 属性检查函数名: ```python import cppcheck import re import sys # 调试输出函数 DEBUG_ENABLED = True # 设置为False关闭调试输出 def debug_print(message): if DEBUG_ENABLED: print(f"[DEBUG] {message}", file=sys.stderr) # C++关键字列表 CPP_KEYWORDS = { 'alignas', 'alignof', 'and', 'and_eq', 'asm', 'auto', 'bitand', 'bitor', 'bool', 'break', 'case', 'catch', 'char', 'char16_t', 'char32_t', 'class', 'compl', 'concept', 'const', 'constexpr', 'const_cast', 'continue', 'decltype', 'default', 'delete', 'do', 'double', 'dynamic_cast', 'else', 'enum', 'explicit', 'export', 'extern', 'false', 'float', 'for', 'friend', 'goto', 'if', 'inline', 'int', 'long', 'mutable', 'namespace', 'new', 'noexcept', 'not', 'not_eq', 'nullptr', 'operator', 'or', 'or_eq', 'private', 'protected', 'public', 'register', 'reinterpret_cast', 'requires', 'return', 'short', 'signed', 'sizeof', 'static', 'static_assert', 'static_cast', 'struct', 'switch', 'template', 'this', 'thread_local', 'throw', 'true', 'try', 'typedef', 'typeid', 'typename', 'union', 'unsigned', 'using', 'virtual', 'void', 'volatile', 'wchar_t', 'while', 'xor', 'xor_eq' } # 预处理指令列表 PREPROCESSOR_DIRECTIVES = { '#include', '#define', '#undef', '#if', '#ifdef', '#ifndef', '#else', '#elif', '#endif', '#line', '#error', '#pragma' } def get_token_value(token): """安全获取token的字符串值""" if hasattr(token, 'str'): return token.str elif hasattr(token, 'text'): return token.text elif hasattr(token, 'value'): return token.value return None def get_token_line(token): """安全获取token的行号""" if hasattr(token, 'linenr'): return token.linenr elif hasattr(token, 'line'): return token.line elif hasattr(token, 'location') and hasattr(token.location, 'line'): return token.location.line return 0 def is_function_name(token): """检查token是否为函数名(优先使用token.function属性)""" # 首选方法:token.function属性 if hasattr(token, 'function') and token.function: return True # 备选方法:token.isFunction属性 if hasattr(token, 'isFunction') and token.isFunction: return True # 回退方法:检查是否是标识符且不是关键字 token_str = get_token_value(token) if token_str and token_str not in CPP_KEYWORDS: # 检查是否是有效的函数名模式 if re.match(r'^[a-zA-Z_][a-zA-Z0-9_:~]*$', token_str): # 检查上下文:是否有括号或模板参数 next_token = token.next if hasattr(token, 'next') else None while next_token: next_str = get_token_value(next_token) if next_str == '(' or next_str == '<': return True if next_str in (';', '{', '}', ']', ')'): return False next_token = next_token.next return False def is_preprocessor(token): """检查token是否为预处理指令""" # 首选方法:token.preprocessor属性 if hasattr(token, 'preprocessor') and token.preprocessor: return True # 备选方法:token.isPreprocessor属性 if hasattr(token, 'isPreprocessor') and token.isPreprocessor: return True # 回退方法:检查字符串是否以#开头 token_str = get_token_value(token) if token_str and token_str.startswith('#'): return True # 检查是否在预处理块中 if hasattr(token, 'previous') and token.previous: prev_str = get_token_value(token.previous) if prev_str and prev_str.startswith('#'): return True return False def is_comment(token): """检查token是否为注释""" token_str = get_token_value(token) if not token_str: return False # 检查注释标记 if token_str.startswith('//') or token_str.startswith('/*') or token_str.startswith('*/'): return True # 检查token类型属性 if hasattr(token, 'isComment') and token.isComment: return True if hasattr(token, 'comment') and token.comment: return True return False def find_matching_brace(start_token): """找到与起始花括号匹配的结束花括号""" depth = 1 current = start_token.next if hasattr(start_token, 'next') else None while current: token_str = get_token_value(current) if token_str == '{': depth += 1 elif token_str == '}': depth -= 1 if depth == 0: return current current = current.next if hasattr(current, 'next') else None return None def create_token_list(cfg): """创建兼容所有版本的token列表""" token_list = [] # 尝试不同版本的tokenlist属性 token_sources = [ getattr(cfg, 'tokenlist', None), getattr(cfg, 'tokens', None), getattr(cfg, 'rawTokens', None), getattr(cfg, 'tokenStream', None) ] for source in token_sources: if source is None: continue # 如果是列表类型 if isinstance(source, list): token_list = source break # 如果是链表类型 if hasattr(source, 'next'): current = source while current: token_list.append(current) current = current.next if hasattr(current, 'next') else None break debug_print(f"Created token list with {len(token_list)} tokens") return token_list def get_function_body_lines(start_token): """获取函数体非空非注释行数""" end_brace = find_matching_brace(start_token) if not end_brace: return 0 lines = set() current = start_token while current and current != end_brace.next: # 跳过预处理指令、注释和空行 if not (is_preprocessor(current) or is_comment(current)): current_str = get_token_value(current) if current_str and not current_str.isspace(): line_nr = get_token_line(current) if line_nr > 0: lines.add(line_nr) debug_print(f"Counting line {line_nr}: {current_str}") current = current.next if hasattr(current, 'next') else None return len(lines) def get_function_name(token): """获取完整的函数名称""" # 检查是否是析构函数 prev_token = token.previous if hasattr(token, 'previous') else None if prev_token and get_token_value(prev_token) == '~': return '~' + get_token_value(token) # 检查是否有作用域限定符 name_parts = [get_token_value(token)] check_token = prev_token while check_token: token_str = get_token_value(check_token) if token_str == '::': prev_token = check_token.previous if prev_token: name_parts.insert(0, get_token_value(prev_token)) name_parts.insert(0, '::') check_token = prev_token.previous continue break return ''.join(name_parts) @cppcheck.checker def check_function_length(cfg, data): """ 检查函数体是否超过阈值行数(非空非注释行) """ MAX_LINES = 80 reported_errors = set() # 创建兼容的token列表 token_list = create_token_list(cfg) # 遍历所有token for token in token_list: token_str = get_token_value(token) if token_str is None: continue # 检查是否为函数名(优先使用token.function属性) if is_function_name(token): debug_print(f"Found function name: {token_str}") # 查找函数体起始花括号 next_token = token while next_token: token_str = get_token_value(next_token) if token_str == '{': break if token_str == ';': # 函数声明,没有函数体 next_token = None break next_token = next_token.next if hasattr(next_token, 'next') else None if not next_token or get_token_value(next_token) != '{': debug_print("No function body found") continue # 确保花括号位置唯一 brace_key = (get_token_line(next_token), get_token_column(next_token)) if brace_key in reported_errors: continue reported_errors.add(brace_key) # 统计函数体行数 line_count = get_function_body_lines(next_token) debug_print(f"Function body lines: {line_count}") if line_count > MAX_LINES: # 获取完整的函数名 func_name = get_function_name(token) # 避免重复报告 error_key = (get_token_line(token), f"function:{func_name}") if error_key not in reported_errors: cppcheck.reportError( next_token if hasattr(next_token, 'linenr') else token, 'style', f"Function '{func_name}' exceeds {MAX_LINES} lines ({line_count} lines)." ) reported_errors.add(error_key) debug_print(f"Reported long function: {func_name}") # 兼容不同版本的Cppcheck插件API if hasattr(cppcheck, 'register'): @cppcheck.register def function_length(cfg, data): return check_function_length(cfg, data) else: # 旧版本兼容 cppcheck.checkers.append(('function_length', check_function_length)) # 版本诊断输出 debug_print(f"Cppcheck Python插件API版本: {cppcheck.__version__ if hasattr(cppcheck, '__version__') else '未知'}") if token_list and len(token_list) > 0: debug_print(f"Token对象属性: {dir(token_list[0])}") ``` ### 关键改进解释: 1. **优先使用 `token.function` 属性**: ```python def is_function_name(token): """优先使用token.function属性检查函数名""" if hasattr(token, 'function') and token.function: return True ... ``` 2. **增强的函数名识别**: - 支持析构函数(`~ClassName`) - 支持作用域限定符(`Namespace::Class::function`) ```python def get_function_name(token): """获取完整的函数名称""" # 检查是否是析构函数 if prev_token and get_token_value(prev_token) == '~': return '~' + get_token_value(token) ... ``` 3. **改进的函数体行数统计**: ```python def get_function_body_lines(start_token): """获取函数体非空非注释行数""" # 跳过预处理指令、注释和空行 if not (is_preprocessor(current) or is_comment(current)): ... ``` 4. **更可靠的注释检测**: ```python def is_comment(token): """检查token是否为注释""" token_str = get_token_value(token) if token_str and (token_str.startswith('//') or token_str.startswith('/*')): return True ... ``` 5. **优化的函数体定位**: - 简化了函数体定位逻辑 - 直接查找最近的 `{` 符号 ```python # 查找函数体起始花括号 while next_token: token_str = get_token_value(next_token) if token_str == '{': break ... ``` ### 使用建议: 1. **自定义配置**: ```python # 在文件开头修改这些常量 MAX_LINES = 100 # 函数最大行数 DEBUG_ENABLED = False # 关闭调试输出 ``` 2. **跳过特定函数**: ```python # 在报告错误前添加 SKIP_FUNCTIONS = {'main', 'TestFunction'} if func_name in SKIP_FUNCTIONS: debug_print(f"Skipping function: {func_name}") continue ``` 3. **特殊函数处理**: ```python # 为不同函数类型设置不同阈值 if func_name.startswith('test_') or func_name.endswith('Test'): func_max_lines = 150 elif func_name == 'main': func_max_lines = 120 else: func_max_lines = MAX_LINES if line_count > func_max_lines: ... ``` ### 版本兼容性处理: 1. **属性回退机制**: - 优先使用 `token.function` - 回退到 `token.isFunction` - 最后使用命名模式匹配 2. **API注册兼容**: ```python if hasattr(cppcheck, 'register'): @cppcheck.register def function_length(cfg, data): return check_function_length(cfg, data) else: cppcheck.checkers.append(('function_length', check_function_length)) ``` 3. **诊断输出**: ```python debug_print(f"Cppcheck Python插件API版本: {cppcheck.__version__}") debug_print(f"Token对象属性: {dir(token_list[0])}") ``` 这个解决方案优先使用 `token.function` 属性识别函数名,同时保持了与各种 Cppcheck 版本的兼容性,并通过详细的调试输出帮助诊断问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值