skip to Main Content

I was working on a personal project and I made this kind of code (in a static little helper function) :

char *tmp = NULL;
if ((tmp = strchr(mode, 'b') != NULL) && tmp - mode < 3) return BINARY_MODE;
else // ...

Then when I tried to compile with GCC 12 (Ubuntu 12.2.0-3ubuntu1), I had this warning :

warning: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
   31 |     if ((tmp = strchr(mode, 'b') != NULL) && tmp - mode < 3) return BINARY_MODE;
      |              ^

The only thing I tried that solved the problem (at least that suppressed the warning) was to assign the return value of strchr before the conditional.
Is this a bug or did I just miss something ? In both cases the resulting program was working as I expected though.

EDIT

Due to the fact that I should have let the initial code I posted (that wasn’t the code I wanted to post), here is the previous one (that was actually good), so everyone can understand the different answers :

char *tmp = NULL;
if ((tmp = strchr(mode, 'b')) != NULL && tmp - mode < 3) return BINARY_MODE;
else // ...

2

Answers


  1. Before the question was hacked

    The compiler is seeing:

    if ((tmp = strchr(mode, 'b') != NULL) && tmp - mode < 3) return BINARY_MODE;
    

    You are claiming you have:

    if ((tmp = strchr(mode, 'b')) != NULL && tmp - mode < 3) return BINARY_MODE;
    

    Notice the difference in the number of close parentheses ) after the 'b' and after NULL. What you claim you’ve got is the correct code — now you need to make sure that’s what the compiler sees.

    After the question was hacked

    The compiler is still seeing the erroneous code, but you now admit that you gave it the erroneous code.

    That code is equivalent to writing:

    if ((tmp = (strchr(mode, 'b') != NULL)) && tmp - mode < 3) return BINARY_MODE;
    

    which assigns the result of the comparison to tmp — assigning an int to a char * as the compiler complains in the error message.

    The correct code is what you originally claimed to have. You need to ensure that the assignment is compared with null, not the result of calling strchr().

    So, the fix is to write:

    if ((tmp = strchr(mode, 'b')) != NULL && tmp - mode < 3) return BINARY_MODE;
    

    The code ‘appeared’ to work because you assigned either 0 or 1 to tmp, and then subtracting the mode pointer from that gives a negative ptrdiff_t value, and that result is negative, and hence less than 3. I think you probably tested with b present and not with b absent.

    Login or Signup to reply.
  2. In this subexpression:

    (tmp = strchr(mode, 'b') != NULL)
    

    The inequality operator != has higher precedence than the assignment operator =. So the above is equivalent to:

    (tmp = (strchr(mode, 'b') != NULL))
    

    Which means you’re assigning the result of a comparison, which has type int and results in the values 0 or 1, and assigning that to a char *, which is why you’re getting the warning.

    You need to add parenthesis to perform the assignment first:

    ((tmp = strchr(mode, 'b')) != NULL)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search