The behavior is correct.
Per the POSIX str\[n\]casecmp() specification:
When the
LC_CTYPEcategory of the locale being used is from the POSIX locale, these functions shall behave as if the strings had been converted to lowercase and then a byte comparison performed. Otherwise, the results are unspecified.
That is also part of the NOTES section of the Linux man page:
The POSIX.1-2008 standard says of these functions:
When the LC_CTYPE category of the locale being used is from
the POSIX locale, these functions shall behave as if the
strings had been converted to lowercase and then a byte
comparison performed. Otherwise, the results are unspecified.
Why?
As @HansOlsson pointed out in his answer, doing case-insensitive comparisons between only letters and allowing all other comparisons to have their “natural” results as done in strcmp() would break sorting.
If 'A' == 'a' (the definition of a case-insensitive comparison) then '_' > 'A' and '_' < 'a' (the “natural” results in the ASCII character set) can not both be true.