6

I was looking at an example and I saw this:

char *str;

/* ... */

if (!str || !*str) {
    return str;
}

Does it mean it's empty or something?

M.M
  • 138,810
  • 21
  • 208
  • 365
PTN
  • 1,658
  • 5
  • 24
  • 54
  • 3
    In C, `!x` is equivlent to `x == 0`, always – M.M Jul 31 '15 at 04:00
  • 1
    This is a check, whether str points to anything, and whether than thing is not a null character. – dtech Jul 31 '15 at 04:01
  • I've seen this example before. This code comes from the subroutine `char* segfault_maybe(void)`. – geometrian Jul 31 '15 at 04:01
  • @imallett I see. I assume that OP has just provided `char *str;` to show the original definition of `str` and in the 'real code' there is some stuff in between – M.M Jul 31 '15 at 04:06
  • Sorry about my char *str. Yeah I just want to show that str is a normal string. The is some stuff in my actual code. – PTN Jul 31 '15 at 04:09
  • @MattMcNabb, PTN, I figured as much. I typically write something like `char* str = /*something*/;` to help dissuade pedant gits like myself. – geometrian Jul 31 '15 at 04:10

4 Answers4

6

str is a char pointer. ! negates it. Basically, !str will evaluate to true (1) when str == NULL.

The second part is saying, (if str points to something) evaluate to true (1) if the first character is a null char ('\0') - meaning it's an empty string.

Note:
*str dereferences the pointer and retrieves the first character. This is the same as doing str[0].

pushkin
  • 9,575
  • 15
  • 51
  • 95
4

!str means that there is no memory allocated to str. !*str means that str points to an empty string.

unxnut
  • 8,509
  • 3
  • 27
  • 41
  • `str = malloc( 42 ); free( str ); assert( ! str ); /* fails */` – Potatoswatter Jul 31 '15 at 03:55
  • 1
    @Potatoswatter Evaluating `str` in your the last expression causes undefined behaviour, therefore `!str` is moot. IOW If `!str` is evaluated without UB having been triggered, then it's equivalent to testing whether `str` points to allocated memory (or one past the end) – M.M Jul 31 '15 at 03:57
  • @MattMcNabb Could you let me know what UB means? I don't know that acronym. – Ely Jul 31 '15 at 04:08
  • @MattMcNabb Is that true in C? I don't see anything in §6.3.2.3 or §6.5.16.1. – Potatoswatter Jul 31 '15 at 04:09
  • I still stand by the fact that `!str` means there is no memory allocated to `str`. That does *not* mean that `str` having a non-zero value implies that it is pointing to some allocated memory. – unxnut Jul 31 '15 at 04:09
  • `!str` does imply that there is no memory allocated, but the word "means" suggests identical conditions. – Potatoswatter Jul 31 '15 at 04:12
  • @Potatoswatter see C99 6.2.4/2 and 6.2.6.1/5 . More discussion [here](http://stackoverflow.com/questions/17024866/when-is-it-valid-to-access-a-pointer-to-a-dead-object) – M.M Jul 31 '15 at 04:12
  • 1
    @MattMcNabb Thanks. So, in fact, an implementation could implement `free` as a function-like macro (§7.1.4) which assigns `NULL` to its argument, using the latitude that the value is indeterminate. (This would require some magic to distinguish lvalues, but it would be conforming.) My assertion would not fire. – Potatoswatter Jul 31 '15 at 04:15
  • 2
    @unxnut I assume you mean "`!str` evaluating *true* means there is no memory allocated to `str`". We were pointing out a caveat (that your answer possibly should mention) that if `str` is a dangling pointer (and therefore does not point to allocated memory), then `!str` causes undefined behaviour; so the program may appear to run as if `!str` evaluated true. – M.M Jul 31 '15 at 04:17
2

Before asking you can do small tests.

#include <stdio.h>

int main()
{
    char *str = "test";
    printf("%d\n",*str);
    printf("%c\n",*str); // str[0]
    printf("%d\n",str);
    if (!str || !*str)
    {
        printf("%s",str);
    }

    return 0;
}

meaning of ! is negation. Except 0 every value is true for if condition. Here, str and *str return values that are not 0. So, you can make an inference.

0

The first expression !str evaluates true if str is set to NULL, and false if set to anything else regardless of whether the memory pointed to is still allocated or not. This can lead to undefined behavior if str is left set to memory that is no longer active.

The second expression !*str evaluates true if the value at the address in str is \0 (null character), but is not evaluated at all if !str evaluated true due to the short-circuiting action of the boolean OR operator.

doppelheathen
  • 388
  • 4
  • 8