strncmp

Compares the first n bytes of two strings, case sensitively and binary safely.

Signature
strncmp(string $string1, string $string2, int $length): int
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$string1stringThe first string.
$string2stringThe second string.
$lengthintNumber of characters to use in the comparison.

Return value

intA value less than 0 if string1 is less than string2, a value greater than 0 if string1 is greater than string2, and 0 if they are equal.

Errors

Throws a ValueError if length is negative.

Changelog

  • PHP 8.2.0This function is no longer guaranteed to return strlen($string1) - strlen($string2) when string lengths are not equal, but may now return -1 or 1 instead.

strncmp() compares at most the first n bytes of two strings. It is strcmp() with a hard limit, and it is binary safe — null bytes and arbitrary binary data are compared like any other byte.

When to reach for it

Use it for prefix tests and for cheap ordering of long strings where only the head matters. Checking that a resolved path stays inside a base directory, filtering records by a country or type prefix, or peeking at a file's magic bytes are all a good fit, because the comparison stops after n bytes instead of scanning megabytes.

Since PHP 8.0, str_starts_with() expresses a plain prefix test more clearly and needs no length argument. Prefer it unless you need the three-way ordering result, a case-insensitive test (strncasecmp()), or a comparison that starts somewhere other than position 0 (substr_compare()).

What trips people up

The length is in bytes. Hard-coding it invites drift, so write strlen($prefix). The length is also not clamped to the shorter string: comparing three bytes of 'ab' against 'abc' is non-zero, not zero.

Only the sign of the return value is meaningful. Since PHP 8.2 it is typically -1, 0 or 1, so never do arithmetic on it.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Confirm a resolved file path still begins with an allowed base directory.
  • Filter records whose reference starts with a given country or type code.
  • Detect a file format from its leading magic bytes without reading the whole file.

Frequently asked questions

What is the difference between strcmp and strncmp?

strcmp compares the whole of both strings; strncmp stops after the number of bytes you pass as the third argument. Use strncmp when only the beginning matters.

Should I use strncmp or str_starts_with?

Use str_starts_with for a plain prefix test — it is clearer and needs no length. Use strncmp when you need the three-way less/equal/greater result for sorting.

Can I use strncmp to compare API tokens?

No. strncmp returns as soon as bytes differ, which leaks timing information. Use hash_equals() for any secret comparison.

More examples

strncmp versus str_starts_with

The first two lines are equivalent, which is why str_starts_with is the clearer choice for a plain prefix test. The third shows that strncmp is case sensitive; strncasecmp would return 0 there.

Example · php
<?php
$s = 'php8.5-cli';

var_dump(strncmp($s, 'php', 3) === 0); // bool(true)
var_dump(str_starts_with($s, 'php'));  // bool(true)
var_dump(strncmp($s, 'PHP', 3) === 0); // bool(false) — case sensitive

echo str_starts_with($s, 'php') ? "starts with php\n" : "no\n";

Filtering by prefix

Only GB-1001 and GB-0003 survive the filter, and array_values reindexes the result so it is a clean list again. array_filter alone would have kept the original keys 0 and 2.

Example · php
<?php
$rows = ['GB-1001', 'US-2002', 'GB-0003', 'DE-4004'];

$gb = array_values(array_filter(
    $rows,
    static fn (string $r): bool => strncmp($r, 'GB-', 3) === 0
));

print_r($gb);
echo count($gb), " GB rows\n";

Discussion

  • Be the first to comment on this lesson.