Why don't my metrics add up?¶
A very common surprise: Comment Lines + Blank Lines + Code Lines ≠ Total Lines, and declarative + executable statements don't sum to the statement total either. That's expected — Understand's counts are designed to overlap, and a few language rules change what gets counted. Here's why.
Any line can count toward several metrics¶
The line and statement metrics are not mutually exclusive. One physical line can satisfy multiple categories at once:
int deltaChange = 5; // Delta needs a minimum of 5
That single line is:
- a code line (
CountLineCode), - a comment line (
CountLineComment), and - both a declarative and an executable line/statement.
So it's counted in all of those metrics. Because comment lines and code lines overlap, they can't be
added to physical lines (CountLine) to get a clean total.
Lines vs statements are different counts¶
CountLineCodeDecl counts lines containing declarative
code; CountStmtDecl counts the declarative statements
themselves — and a line can hold several statements, or a statement can span several lines:
int x, y, z;— 1 declarative line, 3 declarative statements.- A four-line
class MyClass { … };— 4 declarative lines, but far fewer statements.
The same line-vs-statement distinction applies to executable code
(CountLineCodeExe vs
CountStmtExe). Don't expect line counts and statement counts to
line up.
Preprocessor & inactive code (C/C++)¶
For C/C++, the preprocessor changes what "the code" even is:
CountLineInactivecounts lines that the preprocessor turned off — the false side of an#if,#ifdef, etc. By default the main code metrics measure only the active code, so inactive lines aren't inCountLineCode. Understand also provides…WithInactivevariants (e.g.CountLineCodeWithInactive) that include them.CountLinePreprocessorcounts preprocessor directive lines separately.- Macro expansion doesn't affect line counts — line and statement metrics count the source as
written, so there's no "expanded" line count to reconcile. It's
CyclomaticComplexity (and its variants, plusCountPathandKnots) that macro expansion affects, because those come from the control-flow graph — and by default the CFG is built from the fully macro-expanded code, so a macro that hides anif/while/forstill shows up as real branching. C/C++'s "Simplify macro expansions in control flow graph (and metrics)" setting (Project → Configure Project → C++, orund settings -c++simplifymacroexpansion) collapses macro-originated branching into a single block instead, making the function look simpler — but it's not generally recommended, since collapsing arbitrary macro content into one block can produce a control-flow graph that doesn't reflect what the code actually does.
Toggle how inactive code is treated
Whether inactive lines are excluded, included, or both is a project setting
(Project → Configure Project → Metrics, or und settings -metricinactivelines). If your counts
look off in code with heavy #if 0 blocks, check this first.
Declaration vs definition, and headers¶
An entity can be declared in one file and defined in another (a prototype in a header, the body in
a .c/.cpp). Line and complexity metrics attach to the definition, so:
- A header full of prototypes contributes declarative lines but little executable code.
- A function's complexity shows up on the file that defines it, not the ones that declare it.
CountDeclFile splits into
CountDeclFileCode and
CountDeclFileHeader, so header and source files are
counted distinctly.
Aggregates roll up member values¶
Sum…, Avg…, and Max… metrics are computed over an entity's members. A class's
SumCyclomatic is the sum over its methods; its
CountLineCode is the sum of its member functions' code lines.
If a class total doesn't match your manual read of the class body, remember it's aggregating
members — and members declared elsewhere still count.
Per-language differences¶
Not every metric applies to every language, and definitions differ (inactive-line counting is C/C++ only; some object-oriented metrics apply only to class-based languages). The Metrics Browser shows only the metrics valid for the selected entity, so a metric you see on one file may simply be not applicable on another rather than zero.
When in doubt, read the definition¶
Every metric has an exact, per-language definition, a diagram, and the languages it applies to in the metrics catalog — the authoritative answer for "what exactly does this count?"
If you believe a metric is genuinely miscounting (not just overlapping), see contact support.