What are Check Distinct Array Elements- Best Embedded C Programming Course

Need Help or More Information?

Questions about this free C programming course, embedded C training or career guidance? Get in touch.

Free C Programming Course | Arrays

Check Distinct Array Elements

Detect duplicate values in 1-D arrays and 2-D matrices with clean, embedded-friendly C.

Duplicate values cause real bugs in firmware: two sensors answering to the same I2C address, two tasks sharing one priority slot, two CAN message IDs colliding in a lookup table. In this lecture of our free C programming course you will learn how to check distinct array elements in C, first for a 1-D array and then for a 2-D matrix. The idea is simple, but the way you write it decides whether it runs in microseconds or milliseconds on a small microcontroller. This free C tutorial keeps the focus on embedded C programming, so every method comes with its RAM and CPU cost.

What You Will Learn

  • How to check distinct array elements in C using the pairwise comparison method
  • How to return the exact positions of the first clash instead of a bare true or false
  • A faster one-pass method that uses a small “seen” table, ideal for byte-sized IDs
  • How to test a matrix for duplicates by walking it as one long row-major line
  • What each approach costs in time and RAM, and which mistakes to avoid

Prerequisites

You should be comfortable with one-dimensional arrays, nested for loops, and passing an array to a function. Two-dimensional array declaration from the earlier lectures is needed for the matrix part. Any C11 compiler works; every program here was built with gcc -std=c11 -Wall -Wextra and produced zero warnings.

Why Check Distinct Array Elements in C?

An array is “distinct” when no value appears twice. That sounds like a classroom exercise, yet the same test shows up all over embedded work:

SituationWhat must be unique
I2C bus with many sensorsEvery 7-bit device address
CAN or BLE firmwareMessage IDs or handle numbers in a table
Pin multiplexing tableEach GPIO pin assigned only once
RTOS configurationTask priorities or event flag bits
Quiz or lottery softwareDrawn numbers, roll numbers, seat numbers

Validating such tables at start-up, or in a unit test, catches configuration mistakes before they become strange field failures.

Method 1: Check Distinct Array Elements by Pairs

The direct way to check distinct array elements in C is to compare element 0 with all elements after it, then element 1 with all elements after it, and so on. You never compare an element with itself, and you never repeat a pair, so an array of n items needs exactly n(n-1)/2 comparisons.

Pairs examined for an array of 4 elements

Outer index iInner index jPairs compared
01, 2, 33
12, 32
231
3none0
Total6 = 4 x 3 / 2

The program below goes one step further than a yes/no answer. It reports which two positions clash, which is far more useful when you are debugging a configuration table.

Method 1 and Method 2 together: ex51a.c

/* ex51a.c - are all elements of a 1-D array distinct? */
#include <stdio.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

/* Approach 1: compare every pair. Works for any int values. */
static bool find_duplicate(const int *a, size_t n, size_t *first, size_t *second)
{
    for (size_t i = 0; i + 1 < n; i++) {
        for (size_t j = i + 1; j < n; j++) {
            if (a[i] == a[j]) {
                *first = i;
                *second = j;
                return true;
            }
        }
    }
    return false;
}

/* Approach 2: one pass with a "seen" table. Only for small value ranges (bytes). */
static bool all_distinct_u8(const uint8_t *a, size_t n)
{
    bool seen[256] = { false };

    for (size_t i = 0; i < n; i++) {
        if (seen[a[i]])
            return false;
        seen[a[i]] = true;
    }
    return true;
}

static void report(const char *label, const int *a, size_t n)
{
    size_t i, j;

    if (find_duplicate(a, n, &i, &j))
        printf("%-10s: value %d repeats at index %zu and %zu\n", label, a[i], i, j);
    else
        printf("%-10s: all %zu elements are distinct\n", label, n);
}

int main(void)
{
    int sensor_ok[]  = { 12, 7, 33, 5, 21 };
    int sensor_bad[] = { 12, 7, 33, 5, 7, 21 };
    uint8_t node_ok[]  = { 0x10, 0x22, 0x31, 0x44 };
    uint8_t node_bad[] = { 0x10, 0x22, 0x10, 0x44 };

    report("sensor_ok", sensor_ok, sizeof sensor_ok / sizeof sensor_ok[0]);
    report("sensor_bad", sensor_bad, sizeof sensor_bad / sizeof sensor_bad[0]);

    printf("node_ok   : %s\n", all_distinct_u8(node_ok, 4) ? "distinct" : "duplicate found");
    printf("node_bad  : %s\n", all_distinct_u8(node_bad, 4) ? "distinct" : "duplicate found");
    return 0;
}

How find_duplicate Works

Control flow of find_duplicate

i = 0 then j = i + 1 then a[i] == a[j] ?
yes then store i and j through pointers then return true
no then j++ until n then i++ until n – 1 then return false
  • The outer loop condition is i + 1 < n instead of i < n - 1. With an unsigned size_t and n == 0, the expression n - 1 wraps around to a huge number and the loop would run off the array. Moving the 1 to the other side avoids that trap.
  • The parameter is const int *a because the function only reads the array. The compiler will now reject any accidental write.
  • The function hands back first and second through pointers. C functions return one value, so extra results travel through pointer parameters.
  • sizeof sensor_ok / sizeof sensor_ok[0] computes the element count at compile time. This only works in the function where the array is declared, a point we study in detail in the lecture on array decay.

Method 2: A Seen Table for Embedded C

Pairwise comparison costs time that grows with the square of the array size. If the values are small, you can trade a little RAM for speed. Create a table with one flag per possible value, then walk the array once. The first time you meet a value you mark it; if you meet a marked value, you have found a duplicate.

The function all_distinct_u8 in the program above does this for byte-sized values, using a 256-entry bool table. It finishes in at most n steps. On a tight microcontroller you can shrink the table to 32 bytes by storing one bit per value inside eight uint32_t words, which is the usual bitmap trick.

Limit of the seen table: the value itself is used as an index. Negative numbers or values above the table size would read outside the array, which is undefined behaviour. Use this method only when the range of values is small and known.

Build and Run

gcc -std=c11 -Wall -Wextra -o ex51a ex51a.c
./ex51a

Expected output:

sensor_ok : all 5 elements are distinct
sensor_bad: value 7 repeats at index 1 and 4
node_ok   : distinct
node_bad  : duplicate found

Check Distinct Elements in a Matrix

A matrix is the same problem with a different address calculation. Row-major storage means a 3 x 4 matrix sits in memory as 12 integers in one unbroken line: all of row 0, then all of row 1, then all of row 2. If you number those cells 0 to 11, position p lives at row p / COLS and column p % COLS.

The same 3 x 4 matrix as a flat line of 12 cells

Flat position p01234567891011
Row (p / 4)000011112222
Column (p % 4)012301230123

With that mapping, a matrix check becomes the pairwise method again: take every pair of flat positions p < q and compare the two cells.

Program: ex51b.c

/* ex51b.c - are all elements of a matrix distinct? */
#include <stdio.h>
#include <stdbool.h>

#define COLS 4

/* Treat the matrix as one long row-major line of rows*COLS cells. */
static bool matrix_is_distinct(const int m[][COLS], int rows)
{
    int total = rows * COLS;

    for (int p = 0; p < total - 1; p++) {
        for (int q = p + 1; q < total; q++) {
            int pr = p / COLS, pc = p % COLS;   /* flat position -> row, col */
            int qr = q / COLS, qc = q % COLS;

            if (m[pr][pc] == m[qr][qc]) {
                printf("  clash: (%d,%d) and (%d,%d) both hold %d\n",
                       pr, pc, qr, qc, m[pr][pc]);
                return false;
            }
        }
    }
    return true;
}

int main(void)
{
    int good[3][COLS] = {
        {  4,  9,  1,  7 },
        {  3,  8,  2,  6 },
        {  5, 12, 10, 11 }
    };
    int bad[3][COLS] = {
        {  4,  9,  1,  7 },
        {  3, 10,  2,  6 },
        {  5, 12, 10, 11 }
    };

    printf("matrix good:\n");
    printf("  %s\n", matrix_is_distinct(good, 3) ? "all distinct" : "has duplicates");
    printf("matrix bad:\n");
    printf("  %s\n", matrix_is_distinct(bad, 3) ? "all distinct" : "has duplicates");
    return 0;
}

The parameter const int m[][COLS] leaves the first dimension empty but must name the second. The compiler needs COLS to turn m[r][c] into the address m + r * COLS + c. The row count travels as a separate argument.

The “bad” matrix, with the clashing cells highlighted

RowCol 0Col 1Col 2Col 3
04917
131026
25121011
gcc -std=c11 -Wall -Wextra -o ex51b ex51b.c
./ex51b

Expected output:

matrix good:
  all distinct
matrix bad:
  clash: (1,1) and (2,2) both hold 10
  has duplicates

Cost Comparison

Elements (n)Pairwise comparisonsSeen-table steps
104510
1004,950100
1,000499,5001,000

For a 20-entry configuration table the pairwise version is perfectly fine and needs no extra RAM. For a stream of thousands of byte-sized samples, the seen table wins by a wide margin. A third option, sorting a copy of the array and comparing neighbours, costs about n log n steps and works for any value range, but it needs a spare copy of the data.

Real-World Uses

  • Start-up self-check: loop over a table of peripheral addresses and halt with an error code if two entries match.
  • Unit tests: assert that a generated ID list contains no repeats.
  • Data validation: reject a packet whose list of requested channel numbers repeats a channel.

Common Mistakes and Troubleshooting

  • Starting the inner loop at j = i. Every element equals itself, so the function would report a duplicate every time.
  • Comparing only neighbours. a[i] == a[i+1] finds duplicates only in a sorted array.
  • Dividing by ROWS instead of COLS. The flat position to row and column mapping always uses the column count.
  • Using a seen table with unchecked values. A value of 300 in a bool seen[256] table silently corrupts memory.
  • Measuring size inside a function. sizeof a on a parameter gives the pointer size, so always pass the element count.

Best Practices to Check Distinct Array Elements

  • Mark read-only parameters const.
  • When you check distinct array elements, return the positions of the clash, not only a flag, so error messages are useful.
  • Choose the algorithm from the data range: pairwise for small tables, seen table for byte-sized values, sort-and-scan for everything else.
  • Treat data from UART, SPI or the network as untrusted. Check that the length fits your table before you use it as an index.

Summary and Key Takeaways

  • To check distinct array elements in C, compare each pair once, never an element with itself.
  • The pairwise method needs n(n-1)/2 comparisons and no extra memory.
  • A seen table needs one pass but extra RAM and a bounded value range.
  • A matrix is just a 1-D line in row-major order; use p / COLS and p % COLS to find a cell.

Knowing how to check distinct array elements in C is a small skill with a big lesson: the same task can be solved with very different time and memory costs, and good embedded C programming means picking the cost that fits your hardware. In the next lecture we move to square matrices and add up their two diagonals.

Frequently Asked Questions

How do I check distinct array elements in C without extra memory?

Use two nested loops with the inner index starting at i + 1. It needs no extra arrays, only a few integer variables.

What is the time complexity of the pairwise duplicate check?

It is O(n squared) in the worst case, which happens when all elements are distinct, because every pair gets compared.

When should I use the seen table instead?

When values come from a small known range such as bytes. It runs in O(n) time at the price of a table sized to the value range.

Can I sort the array first?

Yes. After sorting, any duplicates sit next to each other, so one pass comparing neighbours finds them. Sort a copy if you must keep the original order.

Why is the matrix parameter written const int m[][COLS]?

The compiler needs the column count to compute addresses, while the row count can stay open. The const keyword promises the function will not modify the matrix.

Does this work for floating-point arrays?

The logic is the same, but comparing floats with == is unreliable after calculations. Compare with a small tolerance instead.

Keep Building Your Embedded C Skills

This lecture is part of the EmbeddedPathashala free C programming course, a free C tutorial written for students who want to write solid embedded C programming code. Compile every program yourself, change the data, and break things on purpose.

Need Help or More Information?

Questions about this free C programming course, embedded C training or career guidance? Get in touch.

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *