Different compilers are giving different outputs for the same logic in my algorithm.
I wrote the following code for a C code exercise.
The code checks for the longest string in a string vector.
But the same logic gives two different outputs.
Here's what is happening. I have no idea what I did wrong.
First version - without a printf() inside the if condition
Here the if (j > longest)
just attributes new values for int longest
and int index
.
#include <stdio.h>
int main(void) {
char *vs[] = {"jfd", "kj", "usjkfhcs", "nbxh", "yt", "muoi", "x", "rexhd"};
int longest, index = 0;
/* i is the index for elements in *vs[].
* "jfd" is 0, "kj" is 1... */
for (int i = 0; i < sizeof(*vs); i ) {
/* j if the index for string lengths in vs[].
* for "jfd", 'j' is 0, 'f' is 1... */
for (int j = 0; vs[i][j] != '\0'; j ) {
/* if j is longer than the previous longest value */
if (j > longest) {
longest = j;
index = i;
}
}
}
printf("Longest string = %s\n", vs[index]);
return 0;
}
I ran it on https://replit.com/. It gave the unexpected output for longest string of "jfd". https://replit.com/@Pedro-Augusto33/Whatafuck-without-printf?v=1
Second version - with a printf() inside the if condition
Now I just inserted a printf() inside the if (jf > longest)
condition, as seen in the code block bellow.
It changed the output of my algorithm. I have no idea how or why.
#include <stdio.h>
int main(void) {
char *vs[] = {"jfd", "kj", "usjkfhcs", "nbxh", "yt", "muoi", "x", "rexhd"};
int longest, index = 0;
/* i is the index for elements in *vs[].
* "jfd" is 0, "kj" is 1... */
for (int i = 0; i < sizeof(*vs); i ) {
/* j if the index for string lengths in vs[].
* for "jfd", 'j' is 0, 'f' is 1... */
for (int j = 0; vs[i][j] != '\0'; j ) {
/* if j is longer than the previous longest value */
if (j > longest) {
printf("Whatafuck\n");
longest = j;
index = i;
}
}
}
printf("Longest string = %s\n", vs[index]);
return 0;
}
I also ran it on https://replit.com/. It gave the expected output for longest string of "usjkfhcs". https://replit.com/@Pedro-Augusto33/Whatafuck-with-printf?v=1
Trying new compilers
After replit.com giving two different outputs, I tried another compiler to check if it also behaved strangely. https://www.onlinegdb.com/online_c_compiler gives random outputs. Sometimes it's "jfd", sometimes it's "usjkfhcs". https://onlinegdb.com/iXoCDDena
Then I went to https://www.programiz.com/c-programming/online-compiler/ . It always gives the expected output of "usjkfhcs".
So, my question is: why are different compilers behaving so strangely with my algorithm? Where is the flaw of my algorithm that makes the compilers interpret it different?
CodePudding user response:
The code does not make sense.
For starters the variable longest
was not initialized
int longest, index = 0;
So using it for example in this statement
if (j > longest) {
invokes undefined behavior.
In this for loop
for (int i = 0; i < sizeof(*vs); i ) {
the expression sizeof( *vs )
is equivalent to expression sizeof( char * )
and yields either 4
or 8
depending on the used system. It just occurred such a way that the array was initialized with 8
initializers. But in any case the expression sizeof( *vs )
does not provide the number of elements in an array and its value does not depend on the actual number of elements.
Using the if statement within the for loop in each iteration of the loop
for (int j = 0; vs[i][j] != '\0'; j ) {
/* if j is longer than the previous longest value */
if (j > longest) {
longest = j;
index = i;
}
}
Also does not make sense. It does not calculate the exact length of a string that is equal to j
after the last iteration of the loop. So in general such a loop shall not be used for calculating length of a string.
Consider a string for example like "A"
. Using this for loop you will get that its length is equal to 0
while its length is equal to 1
..
It seems you are trying to find the longest string a pointer to which stored in the array.
You could just use standard C string function strlen
declared in header <string.h>
. If to use your approach with for loops then the code can look the following way
#include <stdio.h>
int main(void)
{
const char *vs[] = { "jfd", "kj", "usjkfhcs", "nbxh", "yt", "muoi", "x", "rexhd" };
const size_t N = sizeof( vs ) / sizeof( *vs );
size_t longest = 0, index = 0;
for ( size_t i = 0; i < N; i )
{
size_t j = 0;
while ( vs[i][j] != '\0' ) j;
if ( longest < j )
{
longest = j;
index = i;
}
}
printf( "Longest string = %s\n", vs[index] );
printf( "Its length = %zu\n", longest );
return 0;
}