qak said:
Equivalent to assemply:
cmp [esi], 'Test'
In C:
// slow and long
if(p[0] == 'T' && p[1] == 'e' && p[2] == 's' && p[3] == 't')...
// have to look up Ascii table, hard to change
if (*(int*)p == 0x54657374)...
Please have a better solution, thanks.
A wonderful little example. Of the proposed solutions, none
exactly match the semantics of "slow and long", and all have
undefined behavior or potential undefined behavior of one
kind or another:
1. As others have pointed out, converting a (char *) pointer
to (int *) may have undefined behavior because of alignment
problems.
2. Assuming there are no alignment problems, accessing parts
of character arrays as (non-character) integer types is still
undefined behavior, because such accesses do not meet the
conditions required by effective type rules.
3. The safest solutions proposed so far are those using
memcmp(). However, these too have undefined behavior if
the area pointed to by 'p' doesn't have at least four
characters remaining. (This problem also applies to
all cases where integer comparison is done.)
Two alternate approaches:
Solution A:
Assuming p points to a string (or the beginning of a string)
that might be less than four characters long, the easiest
safe test is with strncmp(), namely,
strncmp( p, "Test", 4 ) == 0
When p is known to point to a string, strncmp() is safer
than memcmp() as it won't read past the null terminating
byte of the string (and memcmp() may). (In the examples
I looked at the generated code for this looked okay,
meaning mainly that there was no call to the library
function - the compiler was smart enough to do things
inline, which wasn't always true of memcmp().)
Solution B:
If you can count on p pointing to an area of at least four
characters, and want to use the integer comparison trick,
this can be done safely with memcpy() and a union type,
illustrated here with a stand-alone function:
int
is_Test( char p[4] ){
union {
char s[ sizeof(uint32_t) ];
uint32_t u;
} it, test = { "Test" };
memcpy( it.s, p, 4 );
return it.u == test.u;
}
I should add that under these conditions the 'memcmp()'
comparison could be used instead. The code shown here may be
faster than memcmp(), but that depends on a lot of different
things, and should be measured if it's important to be sure.
(The examples I looked at seemed to have better generated
code for this approach than memcmp() did, but I didn't take
any measurements.)
Note the declaration of 'p' in the function parameter list
documents 'p' as being at least four (char) elements long.
If neither of the pre-conditions under (A) or (B) is met,
there is no safe way to match "slow and long" that is better
than what you have written already under "slow and long".