Identical string literals are considered equal? [duplicate] - c

This question already has answers here:
Why is "a" != "a" in C?
(11 answers)
Closed 8 years ago.
I have written the following program:
#include <stdio.h>
main()
{
if("ddd" == "ddd")
printf("equal");
else
printf("not equal");
}
The output is "equal", but according to me, the output should be "not equal" because the string literals are stored in the literal pool or some read only memory (I guess it depends on OS), so both strings should have two different addresses as they are stored at different addresses in memory.
Previously, I have done the same type of example (one year back), and that time the output was "not equal". Now, could anyone tell me, is this due to a change in the C standard, or am I missing something?

It's unspecified for string literals with the same content to have the same address or not. So the output of your program could be equal or it could be not equal, your compiler happens to put them in the same place.
C11 6.4.5 String literals
It is unspecified whether these arrays are distinct provided their elements have the
appropriate values.

Of course, what you do in that condition is a comparison between pointers (use strcmp to compare C strings).
So, I think it is a compiler translation/optimization that "maps" identical literals at the same location in the memory.
EDIT 1:
The following sample confirms what I wrote:
#include <stdio.h>
char* a = "ddd";
char* b = "ddd";
char* c = "ddd";
int main() {
printf ("a => %p\nb => %p\nc => %p\n", a, b, c);
}
The previous program, compiled with gcc using -O0 and executed will print:
a => 0x40060c
b => 0x40060c
c => 0x40060c
I don't know how other compilers will treat the same situation.

When you're comparing two character values (which are not pointers), it is a numeric comparison.
But when you're comparing two string, Base address of strings are compared.If supposed compilers treats as both string are in same location ,then o/p is equal.Otherwise Not.
What you are comparing the two memory addresses for the different strings, which are stored in different locations.so,Not equal.
Even it is read only memory,you are used this for comparison only.You are not modify or not write anything.

Related

C chars add themselves up for no reason [duplicate]

This question already has answers here:
Space for Null character in c strings
(5 answers)
Closed 3 years ago.
I think I'm going insane because I cannot find an explanation to why C is combining my chars.
I've made you guys a test programm...
#include <stdio.h>
#include <stdlib.h>
int main()
{
char alphabet_big[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char alphabet_small[26] = "abcdefghijklmnopqrstuvwxyz";
printf("%s\n", alphabet_small);
return 0;
}
Results: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZV
Why is C combining alphabet_small and alphabet_big? That's not making sense. And why is there a "V" at the end of the char?
I hope someone can provide me an answer to this "problem".
Best regards.
Keep in mind that a C String is defined as a null terminated char array.
Change the declaration and initialization statement here: (for both statements.)
char alphabet_big[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//forces compiler to use only 26 char
//regardless of the count of initializers
//(leaving no room for NULL terminator)
To
char alphabet_big[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//allows compiler to set aside
^^ //the proper space, no matter how many initializers
The first produces undefined behavior when using with any of the string functions, such as strcpy, strcmp, and in this case printf with the "%s" format specifier.
The first produces the following, which is not is not a C string:
|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|?|?|?|
While the 2nd produces the following, which is a C string:
|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|\0|?|?|
Note - The ? symbols used in above illustration depict memory locations that are not owned by the program, and for which the contents are unknown, or may not even exist. A program attempting to access these locations would be invoking undefined behavior.
Normally the library functions expect to find a NUL byte at the end of a string, and the compiler is happy to add it for you automatically except you've told it that alphabet_big has only 26 bytes, essentially avoiding that extra NUL byte, so it combines with what's next.
Remove the 26 and let the compiler count for you.

C - Comparison of Arrays with == works, why? [duplicate]

This question already has answers here:
C optimisation of string literals
(2 answers)
Closed 7 years ago.
I'm a little bit confused. I have the following function:
int comp(char s1[], char s2[]) {
return s1 == s2;
}
As far as I know this compares only the addresses of the first elements from char array s1 and char array s2.
But strange is if I compare (in Visual Studio) two equal char arrays like
comp("test","test");
I got 1 (true) instead of 0 (false). But should the addresses not be different and therefore the result should be always 0?
I'd say this is the result of a compiler optimisation using the same instance of the string. If you did something like this you'd prove == doesn't work as you suggest:
char s1[10];
char s2[10];
strcpy(s1, "test");
strcpy(s2, "test");
printf("%d\n", comp(s1, s2));
It is so because same strings are stored as one string in the string pool during compilation . Therefore both points to the same address as there is only one "test" string in the string pool.
String literals are often reused by optimizing compilers, so if you use the same string literals twice, both will be the exactly same string literals. And your function are comparing pointers, and as both string literals are the same then you are comparing the same pointers which of course will give you a "true" value.
Read about the concept of mutabe and immutable string. String stored in stack when compared returns true but if one string in heap an other in stack it returns false.
Second question is, are you using prpredefined functions to compare 2 string then the functions works as follows
Compare(s1,s2) returns positive zero or negative according as s1 preced, equals or follows s2 in lexicographical ordering basednon unicide character.
Regards.

If statement in C always returning false [duplicate]

This question already has answers here:
Issue with main arguments handling
(3 answers)
Closed 7 years ago.
I am fairly new to C, so am not overly familiar with it's syntax, however I have debugged my code and researched for the correct syntax, and it seems to be correct, I have also changed the scope of the variables to see if this was causing the error.
The if statement should compare two variables, which both hold strings, I have even printed both the variables out to ensure they are the same, however it is still skipping straight to the else section of the if statement. Can anyone give me any pointers on why it will not run the if statement, it just skips straight to 'incorrect'.
The correctWord variable is defined at a different section in the code.
Find full code here.
-UPDATE-
I have now updated the syntax of the code, however it is still returning false.
char correctWord[20];
void userGuess(){
char userWordGuess[20];
printf("Anagram: ");
printf(anagramWord);
printf("Your Guess: ");
scanf("%s",userWordGuess); //Reads in user input
printf(correctWord);
printf(userWordGuess);
if(strcmp(userWordGuess, correctWord) == 0){
printf("Congratulations, you guessed correctly!");
}else{
printf("Incorrect, try again or skip this question");
}
}
You cannot compare strings in C using ==, because this compares the addresses of the strings, not the contents of the string. (which you certainly don't require, and obviously, the addresses of the two strings are not equal too.)
C has a pretty nice function for it : strcmp() which returns 0 if both the strings are equal.
Try using this in your if condition:
if (!strcmp(userWordGuess,correctWord))
{
//Yay! Strings are equal. Do what you want to here.
}
Be sure to #include <string.h> before using strcmp().
In C, you can't compare strings using ==. You will end up comparing the addresses of the strings, which is not the same.
You need to call the strmcp() function, which will return 0 if its arguments (two strings) are equal.
So the code should be if(strcmp(userWordGuess, correctWord) == 0).
You're comparing addresses of different arrays, which will always be unequal.
You need to use strcmp or some other strings library function to compare strings character by character.
userWordGuess == correctWord will compare the pointers (i.e. the locations in memory of the arrays), which are probably not equal.
For string comparision in C, use strcmp (or strncmp):
if (!strcmp(userWordGuess, correctWord)){
/*Strings are equal*/
Use
if(strcmp(userWordGuess, correctWord) == 0) // strings are equal
{
printf("Congratulations, you guessed correctly!");
}
else // not equal
{
printf("Incorrect, try again or skip this question");
}
if both string are equal than if condition will run. otherwise it wil run else
The strings are not first-class citizens in the C language. The strings are represented as either arrays of characters or pointers to such arrays.
In both cases, the variable you use to access the string is a synonym for the address in memory of the first character of the string.
What you compare with userWordGuess == correctWord is not the strings but their addresses in memory. Since userWordGuess and correctWord are two different arrays of characters, their addresses in memory are always different and their comparison will always produce FALSE.
In order to compare the actual string values you have to use the standard function strcmp() or one of its variants (find them at the bottom of the documentation page).
Change in the code:
/** Need to include the header that declares the strcmp() function */
#include <string.h>
char correctWord[20];
void userGuess(){
char userWordGuess[20];
/** stripped some lines here ... */
/** compare the strings, not their addresses in memory */
if (strcmp(userWordGuess, correctWord) == 0) {
/** the rest of your code */
What you are doing here is comparing two pointers. userWordGuess and correctWord point each to the beginning of an array of characters (which is what you defined at the beginning of your example code).
So if you want to compare the two arrays of chars you can use the strcmp function defined in string.h
It is important that you learn the relation between arrays and pointers. Pointer arithmetic is as well important here. Check this out: Arrays, Pointers, Pointer Arithmetic

Why string literals are comparable with pointers? [duplicate]

This question already has answers here:
C Strings Comparison with Equal Sign
(5 answers)
Closed 8 years ago.
If we say:
char *p="name";
then how can we do
if(p=="name"){
printf("able"};//this if condition is true but why?
as "name" here is a string literal and p is a pointer which holds the base address of the string then why the above statement works fine?
It is unspecified behavior whether identical string literals can be considered the same and thus have the same address. So this is not portable behavior. From the draft C99 standard section 6.4.5 String literals:
It is unspecified whether these arrays are distinct provided their elements have the
appropriate values. [...]
If you want to compare two string you should use strcmp.
The C Standard allows the comparison to be true, but it is also allowed to be false (the behavior is unspecified). It depends on the compiler performing common string merging (for which gcc has an option to turn it on or off).
From the gcc 4.8.1 manual:
-fmerge-constants
Attempt to merge identical constants (string constants and floating-point constants)
across compilation units.
This option is the default for optimized compilation if the assembler and linker support it.
Use -fno-merge-constants to inhibit this behavior.
Enabled at levels -O, -O2, -O3, -Os.
-fmerge-all-constants
Attempt to merge identical constants and identical variables.
So what you observe is a compiler performing string merging for the two "name" literals.
Ok, let's disect what this does.
p is a pointer to name\0. So, here you are comparing p (a pointer) to "name" (also a pointer). Well, the only way this will every be true is if somewhere you have p="name" and even then, "name" is not guaranteed to point to the same place everywhere.
I believe what you are actually looking for is either strcmp to compare the entire string or your wanting to do if (*p == 'n') to compare the first character of the p string to the n character
You want to use strcmp() == 0 to compare strings instead of a simple ==, which will just compare if the pointers are the same.
The expression strcmp( p, "name") == 0 will check if the contents of the two strings are the same.
String literals are nothing memory references hence when you do char *p="name"; this, it means nothing but:
|n |a |m | e
/
p
p points to first character of the string literal. So doing this:
p=="name" evaluates to someAddress==someAddress. However this behavior is unspecified.

C Strings Comparison with Equal Sign

I have this code:
char *name = "George"
if(name == "George")
printf("It's George")
I thought that c strings could not be compared with == sign and I have to use strcmp. For unknown reason when I compile with gcc (version 4.7.3) this code works. I though that this was wrong because it is like comparing pointers so I searched in google and many people say that it's wrong and comparing with == can't be done. So why this comparing method works ?
I thought that c strings could not be compared with == sign and I have to use strcmp
Right.
I though that this was wrong because it is like comparing pointers so I searched in google and many people say that it's wrong and comparing with == can't be done
That's right too.
So why this comparing method works ?
It doesn't "work". It only appears to be working.
The reason why this happens is probably a compiler optimization: the two string literals are identical, so the compiler really generates only one instance of them, and uses that very same pointer/array whenever the string literal is referenced.
Just to provide a reference to #H2CO3's answer:
C11 6.4.5 String literals
It is unspecified whether these arrays are distinct provided their elements have the
appropriate values. If the program attempts to modify such an array, the behavior is
undefined.
This means that in your example, name(a string literal "George") and "George" may and may not share the same location, it's up to the implementation. So don't count on this, it may results differently in other machines.
The comparison you have done compares the location of the two strings, rather than their content. It just so happens that your compiler decided to only create one string literal containing the characters "George". This means that the location of the string stored in name and the location of the second "George" are the same, so the comparison returns non-zero.
The compiler is not required to do this, however - it could just as easily create two different string literals, with different locations but the same content, and the comparison would then return zero.
This will fail, since you are comparing two different pointers of two separate strings.
If this code still works, then this is a result of a heavy optimization of GCC, that keeps only one copy for size optimization.
Use strcmp(). Link.
If you compare two stings that you are comparing base addresses of those strings not actual characters in those strings. for comparing strings use strcmp() and strcasecmp() library functions or write program like this. below is not a full code just logic required for string comparison.
void mystrcmp(const char *source,char *dest)
{
for(i=0;source[i] != '\0';i++)
dest[i] = source[i];
dest[i] = 0;
}

Resources