Comparing Character Arrays and String Literals in C++

C - Comparing string literal with character array

strcmp returns 0 when the strings are the same. I have code that uses strcmp comparing character arrays to string literals, and I was quite confused when it wasn't working. Turns out it was wrong for me to assume it would return 1 when the string are the same!

Maybe you've made the same mistake?

Compare char array element to string literal

"." is a string literal. What you want should be a character constant '.'.

Try this:

#include <stdio.h>
#include <string.h>

int main(void) {
const char S[] = "0.9";
if (S[1] == '.') {
puts("got it");
}
return 0;
}

Alternative (but looks worse) way: access an element of the string literal

#include <stdio.h>
#include <string.h>

int main(void) {
const char S[] = "0.9";
if (S[1] == "."[0]) {
puts("got it");
}
return 0;
}

Comparing character arrays and string literals in C++

std::strcmp returns 0 if strings are equal.

Comparing character arrays and string literals in C++ without cstring

Try this:

if (argv[1] == std::string("yes")) { stuff }

If the intent of the exercise is to teach how string comparisons work, then implement a for loop like other answers suggest. However, in C++ you are not supposed to use strcmp - there is a string class for a reason.

Compare string literal vs char array

Arrays (or strings) in many circunstances, are converted to the address of their first element.

In your code, inside the printf(), these addresses are being compared.

To compare the stuff pointed to by the addresses you need strcmp() (for real strings) or memcmp() (for binary data)

char buffer[] = {'e','a','b','g','e','l','e','g','o','n','\000','p','k','n','m','l','\000','j', 'i', 'h'};

int equal1 = memcmp(buffer, "eabgelegon\000pknml\000jih", 20);
printf("%d", equal1);
int equal2 = memcmp(buffer, "eabgelegon\000XXXXXXXXX", 20);
printf("%d", equal2);

int equal3 = strcmp(buffer, "eabgelegon\000pknml\000jih");
printf("%d", equal3);
int equal4 = strcmp(buffer, "eabgelegon\000XXXXXXXXX");
printf("%d", equal4);

Comparison of Pointer to String , Array of Characters and Pointer to Array of Characters

char a[]="hello";

This creates an array like this:

   +---+---+---+---+---+----+
a: | h | e | l | l | o | \0 |
+---+---+---+---+---+----+

The array is modifiable and you can write other characters to it later if you like (although you cannot write more than 5 or 6 of them).

char* b="salam";

This uses a string literal to create a constant string somewhere, that variable b is then a pointer to. I like to draw it like this:

   +-------+
b: | * |
+---|---+
|
V
+---+---+---+---+---+----+
| s | a | l | a | m | \0 |
+---+---+---+---+---+----+

There are two differences here: (1) b is a pointer, not an array as a was. (2) the string here (that b points to) is probably in nonwritable memory. But a was definitely in writable memory.

char* c=a;

Now c is a pointer, pointing at the earlier-declared array a. The picture looks like this:

   +---+---+---+---+---+----+
a: | h | e | l | l | o | \0 |
+---+---+---+---+---+----+
^
|
\
|
+---|---+
c: | * |
+-------+

And the array a was modifiable, so there's no problem doing c[0] = 'r', and we end up sounding like Scooby-Doo and saying:

   +---+---+---+---+---+----+
a: | r | e | l | l | o | \0 |
+---+---+---+---+---+----+
^
|
\
|
+---|---+
c: | * |
+-------+

The key difference (which can be quite subtle) is that a string literal in source code like "hello" can be used in two very different ways. When you say

char a[] = "hello";

the string literal is used as the initial value of the array a. But the array a is an ordinary, modifiable array, and there's no problem writing to it later.

Most other uses of string literals, however, work differently. When you say

char *b = "salam";

or

printf("goodbye\n");

those string literals are used to create and initialize "anonymous" string arrays somewhere, which are referred to thereafter via pointers. The arrays are "anonymous" in that they don't have names (identifiers) to refer to them, and they're also usually placed in read-only memory, so you're not supposed to try to write to them.

Is it undefined behavior to compare a character array char u[10] with a string literal abc

Standard says:

[expr.eq]

The == (equal to) and the != (not equal to) operators group left-to-right.
The lvalue-to-rvalue ([conv.lval]), array-to-pointer ([conv.array]), and function-to-pointer ([conv.func]) standard conversions are performed on the operands...

Hence, we are comparing pointers to the respective arrays.

If at least one of the operands is a pointer, ...
Comparing pointers is defined as follows:

  • If one pointer represents the address of a complete object, and another pointer represents the address one past the last element of a different complete object,72 the result of the comparison is unspecified. [does not apply since neither pointer is past last element]
  • Otherwise, if the pointers are both null, both point to the same function, or both represent the same address, they compare equal. [does not apply since neither is null, neither point to functions, nor represent same address]
  • Otherwise, the pointers compare unequal. [applies]

The behaviour is defined and else branch will be unconditionally executed.

Unconditionally unconditional if-statements imply that there is probably a bug; most likely the author was trying to compare the content of the arrays, which the operator does not do.



"warning: comparison with string literal results in unspecified behavior"

I believe that this warning message is slightly misleading. Comparison with two string literals would be unspecified:

if ("tri" == "tri")

It's unspecified whether this conditional is true or false.

How to compare char* to string literal in C?

Your example implies that your strings are always NUL terminated. In that case, don't bother getting their length ahead of time, since that involves searching for the NUL. Instead, you can do

memcmp(str, "OK", 3);

This way, the NULs get compared too. If your length is > 2, the result will be > 0 and if it's shorter, the result will be < 0.

This is a single function call, and memcmp is virtually guaranteed to be better optimized than your hand-written code. At the same time, don't bother optimizing unless you find this code to be a bottleneck. Keep in mind also that any benchmark I run on my machine will not necessarily apply to yours.

The only real reason to make this change is for readability.

What are Strings in C if not Simply Char Arrays?

In these declarations

char apple1[] = { 'a', 'p', 'p', 'l', 'e', '\0' };
char *apple2 = "apple";
char apple3[] = "apple";

there are declared two arrays apple1 and apple3 that contain the string "apple".

In this declaration

char *apple2 = "apple";

there is declared a pointer to the string literal "apple".

In these calls of printf

printf("%i\n", apple1 == apple2); // 0
printf("%i\n", apple2 == apple3); // 0
printf("%i\n", apple3 == apple1); // 0
printf("%i\n", "apple" == apple1); // 0
printf("%i\n", "apple" == apple2); // 1
printf("%i\n", "apple" == apple3); // 0

there are compared addresses of first characters of different arrays that occupy different extents of memory. Arrays used in expressions with rare exceptions are converted to pointers to their first elements. So the result of the expressions is the integer value 0 except this call

printf("%i\n", "apple" == apple2); // 1

because in this case there are compared pointers to the same string literal (its first character) because it seems the compiler allocated one character array to store the string literal "apple" used in this call and in this declaration of a pointer

char *apple2 = "apple";

You can represent the above declaration and the call of printf the following way

char *apple2 = &"apple"[0];
//...
printf("%i\n", &"apple"[0] == apple2); // 1

However in general even if you will write for example

printf("%i\n", "apple" == "apple");

then the output can be either 0 or 1 depending on how the compiler stores identical string-literals: either as different character arrays or as one character array (it depends on compiler options).

To compare character arrays that contain strings you need to use standard C string function strcmp.



Related Topics



Leave a reply



Submit