Product
Solutions
Resources
Company
Download Trial Book a Demo

MC/DC Explained for DO-178C: From Truth Tables to Certifiable Evidence

Modified Condition/Decision Coverage trips up even experienced teams. We break down independence pairs, masking vs. unique-cause, and exactly what an avionics assessor expects to see in your coverage report — with worked examples you can reproduce.

If you build software for an aircraft, your verification evidence will eventually be read by someone whose job is to not believe you. At Design Assurance Level A — the level reserved for software whose failure could be catastrophic — DO-178C asks for a structural coverage metric that almost no other industry mandates: Modified Condition/Decision Coverage, or MC/DC.

MC/DC has a reputation for being confusing, and the reputation is earned. The definition is short, but its consequences are subtle, and the gap between "we hit 100% line coverage" and "we satisfied MC/DC" is exactly where certification programs lose weeks. This guide walks through what MC/DC actually requires, how to derive the test cases from a truth table, the two accepted forms (unique-cause and masking), and what an assessor will look for in your evidence package.

In one sentence

MC/DC requires you to show that each condition in a decision can, on its own, change the decision's outcome — not merely that every line ran and every branch was taken.

Conditions vs. decisions: the words that matter

Before MC/DC makes sense, two terms have to be precise, because DO-178C and its companion document DO-248C use them in a specific way:

  • A condition is a Boolean operand with no Boolean operator inside it — for example altitude > 1000 or the flag gear_down.
  • A decision is a Boolean expression made of one or more conditions joined by operators such as &&, || and !. An if, while, or ternary all evaluate a decision.

So in if (gear_down && (altitude > 1000 || override)) there is one decision and three conditions. MC/DC is about proving something specific about each of those three conditions.

Where MC/DC sits in the coverage hierarchy

Structural coverage metrics form a ladder. Each rung subsumes the one below it — and DO-178C maps the rungs to assurance levels in Table A-7:

MetricWhat it provesRequired at
StatementEvery line executed at least onceLevel C
Decision (branch)Every decision took both true and falseLevel B
MC/DCEach condition independently affects the outcomeLevel A

The jump from decision coverage to MC/DC is the expensive one. Decision coverage is satisfied by toggling the whole expression true and false. MC/DC insists you prove the contribution of every individual condition — and it does so without the combinatorial explosion of testing all input combinations (which is what Multiple Condition Coverage demands).

Statement coverage passes an audit the way a smoke detector passes a fire drill: it tells you something ran, not that it works.

Why DO-178C reserves MC/DC for Level A

The five Design Assurance Levels (DAL A through E) are tied to the severity of a failure condition, from "catastrophic" down to "no safety effect." The more severe the consequence, the stronger the evidence DO-178C demands that the code's logic has actually been exercised — not just touched.

At Level A, decision coverage alone is not trusted, because a compound decision can be flipped without ever demonstrating that a particular safety-relevant condition matters. Imagine if (sensor_ok || true) — decision coverage can be "satisfied" while the sensor_ok check is dead weight. MC/DC is the criterion that forces that dead weight into the open.

From truth table to independence pairs

Let's make it concrete with a small decision: D = A && (B || C). Three conditions means eight rows in the full truth table:

#ABCD = A && (B || C)
1TTTT
2TTFT
3TFTT
4TFFF
5FTTF
6FTFF
7FFTF
8FFFF

To demonstrate MC/DC we need, for each condition, an independence pair: two rows where only that condition flips, every other condition is held constant, and the decision's outcome flips as a result.

  • A: rows 2 and 6 — only A changes (T→F), and D changes (T→F). ✔
  • B: rows 2 and 4 — only B changes (T→F) with A=T, C=F, and D changes (T→F). ✔
  • C: rows 3 and 4 — only C changes (T→F) with A=T, B=F, and D changes (T→F). ✔

The union of those rows is {2, 3, 4, 6} — four test cases that satisfy MC/DC, instead of all eight combinations. That reduction is the entire point of MC/DC: near-exhaustive logical confidence at linear, not exponential, cost.

The N+1 rule (and why it's a minimum, not a promise)

For a decision with N independent (uncoupled) conditions, MC/DC can always be achieved with a minimum of N + 1 test cases. Our example had N = 3, and indeed four cases sufficed. Treat N+1 as a lower bound for planning, not a target you are guaranteed to hit — operators like || with short-circuit evaluation, and conditions that are coupled, can push the real number higher.

The mental model to keep

  • Pick a condition. Build two test cases where only that condition differs.
  • If the decision's result differs too, you've proven that condition matters.
  • Do that for every condition; the union of all those cases is your MC/DC test set.

Unique-cause vs. masking MC/DC

There are two accepted ways to demonstrate independence, and DO-178C/DO-248C recognize both:

Unique-cause MC/DC

The strict, original form: in the independence pair, only the condition under test may change. Every other condition holds its value. This is the cleanest to defend and the easiest for an assessor to read — but it becomes impossible when conditions are coupled (when one condition's value forces another's, e.g. x > 0 and x > 5).

Masking MC/DC

The form clarified by the certification authorities (CAST-10): a condition's effect is shown when the Boolean logic masks out the other conditions so they cannot influence the outcome. For example, in A && B, holding A = true "unmasks" B — B now drives the result. Masking MC/DC is what lets you handle strongly coupled conditions that unique-cause cannot, and most modern coverage tools and qualified analyzers default to it.

Decide your form up front

State in your verification plan (the SVP/SQAP) which form of MC/DC you use and why. Switching forms midway, or leaving it unstated, is a finding waiting to happen during the audit.

Common mistakes that fail the review

  • Confusing line coverage with MC/DC. 100% statement coverage routinely leaves MC/DC in the 60–80% range. The numbers are not interchangeable.
  • Ignoring short-circuit evaluation. In C/C++/Java, A && B never evaluates B when A is false. Your tool must model this, or your "independence" pairs are fiction.
  • Unjustified coupled conditions. If two conditions cannot be varied independently, you owe the assessor a written rationale, not a silent gap.
  • Counting requirements-free tests. DO-178C wants requirements-based tests first; structural coverage analysis then reveals what those tests missed. Coverage is the gap-finder, not the test designer.
  • Treating dead code and deactivated code the same. Dead code must be removed; deactivated code must be justified and shown to be unreachable in the target configuration.

What a DO-178C assessor expects to see

When your evidence reaches a Designated Engineering Representative or certification authority, they are reconciling three things: your requirements, your tests, and your structural coverage. Concretely, they want:

  • Requirements-based test traceability — every test ties back to a high- or low-level requirement.
  • An MC/DC report at the source level, showing the metric per decision, with the independence pairs (or masking analysis) demonstrable.
  • Analysis of every gap — uncovered conditions explained as dead code, deactivated code, or a documented analysis substituting for a test.
  • Coverage on the right object — structural coverage performed on code built with the same compiler and options as the airborne software, not a convenient host build.
  • Source-to-object traceability at Level A, or additional object-code verification where the compiler introduces structure not visible in the source.

How RKTracer measures MC/DC automatically

Deriving independence pairs by hand is instructive once and tedious forever. RKTracer measures decision, condition, MC/DC and multi-condition coverage natively — and it does so without changing a line of your source. You prefix your existing build command, and it instruments during compilation using the same cross-compiler that builds your shipped firmware, so the coverage you measure is the coverage that flies.

terminal — MC/DC on the real target
# Prefix your normal build — no source edits, no wrappers
$ rktracer make flight_law

  compiler: arm-none-eabi-gcc 12.2 (airborne config)
   instrumented 142 files — source unmodified

$ ctest # run your requirements-based tests
$ rkresults --report html

   Decision  100%
   Condition 100%
   MC/DC     99.2%  (2 conditions justified as deactivated)

RKTracer reports MC/DC per decision and flags the exact conditions still missing an independence pair.

And when a gap is real rather than justified, RKTracer's AI test generation proposes the unit tests that close it — including the boundary cases needed to form the missing independence pair — so reaching Level A coverage becomes an afternoon's work instead of a sprint's.

The bottom line

MC/DC is not arbitrary bureaucracy. It is the most efficient known way to gain near-exhaustive confidence in Boolean logic without testing every input combination, and that is precisely why DO-178C reserves it for the software that absolutely cannot fail. Once you internalize the independence-pair idea — two tests, one condition changing, outcome changing — the truth tables stop being intimidating and start being a checklist.

Get the definition right, choose your form (unique-cause or masking) deliberately, justify every gap, and measure on the target that actually ships. Do that, and the person whose job is not to believe you will have very little left to question.

PN
Priya Nair
Coverage Engineering, RKValidate

Priya works with avionics and automotive teams adopting MC/DC and multi-condition coverage for DO-178C and ISO 26262 programs.

Keep reading
ISO 26262

ISO 26262 Tool Confidence Levels, Demystified

TCL, TD and tool qualification — a clear path to trusting a coverage tool in an ASIL-D workflow.

Read more
Code Coverage

Everything You Need to Know About Code Coverage

Statement, branch, decision, condition, MC/DC and multi-condition — what each metric really proves.

Read more
DO-178C

Measuring Coverage on Targets Without a File System

Streaming structural coverage off bare-metal and constrained RTOS devices over SWO, RTT and JTAG.

Read more

Prove MC/DC on your own code

See RKTracer measure certifiable MC/DC — on host or the real target — and generate the tests that close the gaps. Book a 30-minute demo or run the free trial today.