0

I just created this function to check the equality between two strings by subtracting their Integer values

int EQ(const char* CString1, const char* CString2)
{
    return CString1 - CString2 == 0;
}

However, I'm not sure if this is a safe way to check for char* Strings

It won't work with arrays cause they've different integers so I created other function for that purpose

int EQA(const char* CString1, const char* CString2){
    if(CString1 == NULL || CString2 == NULL)
        return 0;
    int i = strlen(CString1);
    if(i != strlen(CString2))
        return 0;
    while(i>=0){
        if(CString1[i] != CString2[i])
            return 0;
        --i;
    }
    return 1;
}

I didn't try to optimize my second function too much

But when checking on char*, why would I use EQA() or strcmp() over EQ()?

the first one EQ() is much faster than any other standard function I used before
So I really liked using it

I tested it on other machines and it worked but the Integers values of char* differ, also
noticed that these integers depend on which variable is declared first in the code but it's the same integer if they have the same string which makes this function works perfectly, So does it depends on the compiler?

and why different integers?, Is it still safe?

EDIT: Some answers focused on debugging my 2nd example rather than answer my question, So I edited it.

  • You're working too hard `strcmp` is what you need. And both your functions are bugged. `EQA` checks if `CString1` is the prefix of `CString2`, so `EQA("", "hello")` is true for instance. – john Mar 01 '18 at 06:31
  • It's fine to try and rewrite standard functions as a learning exercise, but it's not something to do in real code. – john Mar 01 '18 at 06:32
  • I tried checking strlen() in EQA before posting this but I removed it for clarifying purposes. @john , this is not my original one, but you're right cause I won't use them in real code, I'm trying to understand how they work –  Mar 01 '18 at 06:36
  • 1
    *Please* **don't** abuse `typography`. – n. m. could be an AI Mar 01 '18 at 06:37
  • 2
    @Tas no it isn't safe. It's undefined behaviour to subtract two pointers that do not point to the same array. – n. m. could be an AI Mar 01 '18 at 06:41
  • See my edited answer: in the quest for optimization you've broken the function. EQA says "Hello" and "Jello" are the same. – John3136 Mar 01 '18 at 07:12
  • Well, that's why I said `I didn't try to optimize my second function too much` when posting this question, as a newbie I'd love to debug it btw, thanks xd @John3136 –  Mar 01 '18 at 07:15
  • @n.m. ah I was completely unaware of that. I hope it never comes up, but thanks for letting me know! – Tas Mar 01 '18 at 09:30

4 Answers4

8

Two strings lexicographically equal doesn't mean that they are stored at the same memory location. Subtracting their addresses to compare them may give some erroneous results. Pointer subtraction is meaningless if two pointers doesn't point to elements of the same array or one past the last element of the array.
I would suggest to use standard function strcmp for lexicographic string comparison.

haccks
  • 104,019
  • 25
  • 176
  • 264
5

No.

You can have two copies of the same string at two different locations in memory but your method would say they are different.

char *s1 = "Hello";
char *s2 = strdup(s1);
printf("%d\n", strcmp(s1, s2)); /* prints 0 */
printf("%d\n", s1-s2); /* does not print 0 */

In addition, your EQA function is horribly buggy: EQA("Hello", "h") is going to access memory before the CString2 pointer. Also consider what if CString2 is NULL?

Are you sure this while(i>0 && --i) checks position 0? I think it will say "Hello" and "Jello" are the same... (confirmed. position 0 not checked)

John3136
  • 28,809
  • 4
  • 51
  • 69
  • I edited my question to my original function which I use strlen() first, you're right, I forgot about `NULL` thing, I appreciate pointing that –  Mar 01 '18 at 06:45
5

From 6.5.6p9 (From C standard - N1570 )

When two pointers are subtracted,both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the header.

And also in from standard :-

...If the expressions P and Q point to, respectively, elements x[i] and x[j] of the same array object x, the expression P - Q has the value i−j; otherwise, the behavior is undefined.

This is not right given this section of the standard.(You can not ensure they are pointing to same location or different positions of same array as mentioned above) You have undefined behavior on your code when it doesn't follow the criteria mentioned above.

Also you can't check equality of two strings (nul terminated char arrays in ) subtracting their addresses - how can it check the equality of the content that is there in the address? It can't. Standard didn't provide strcmp for nothing - it is in cases like these you can use it to compare the content of the string.

user2736738
  • 30,591
  • 5
  • 42
  • 56
  • @JohannesSchaub-litb.: If it was allowed to subtract 2 different addresses not necessarily pointing to the same array - it is not good to subtract address and conclude that their content is same - it is nonsense. – user2736738 Mar 01 '18 at 06:31
  • These functions are just for learning, by the way, thanks for your answer :) –  Mar 01 '18 at 06:53
  • @KiraSama.: You have to use `strcmp` to write a legal code - that is my point. I hope you get what I am saying in my answer – user2736738 Mar 01 '18 at 06:54
2

Instead of checking if the difference is 0, just check if they are equal. It will give you the same result, BUT it is not going to tell you if you strings are different but only if your strings are stored in the same place (two identical strings can be stored in different places and will look different with your test).

Camion
  • 1,264
  • 9
  • 22
  • Yup, I understand it now, thank you and all people that made effort to answer my question here, I appreciate them all +1 but I've to choose one simple answer that points to the actual question, you're right checking for the equality directly, what a useless function I made. ^^ –  Mar 01 '18 at 07:35
  • It was not necessarily useless : It can happen that two objects are « identical twins » but we are interested in knowing if they ARE the same (let's say : occupy the same place at the same time), or are just copies of one another. It's just a different problem :-) – Camion Mar 01 '18 at 08:24
  • Re “will look different with your test”: This is not guaranteed by the C standard. If `a` and `b` are pointers to different arrays, the result of `a-b` is not defined by the C standard. It could be zero. – Eric Postpischil Mar 01 '18 at 12:45
  • It could be an unexpected value or cause an error, but i don't believe it could be 0. However, this is why I suggested him to just test if the pointers are equal instead of testing if their difference is zero. – Camion Mar 01 '18 at 23:51