1

I understand that we want to use assert when we want to check for impossible case. In a book I have, I saw the following two examples:

void foo(char* str) { assert ((str+strlen(str)) != NULL); }
void bar(char* str) { assert (str[strlen(str)] != NULL); }

I'm trying to figure out if they are valid checks. As I understand the first example is not valid because we check if the address is NULL and that is not right. But I'm not sure what we are checking in the second example. I'm having hard time understanding when its the right time to use assert. I understand the explanation of "checking impossible cases" but it a bit different for each case.

EDIT: Is there a diffrence between the functions I showed before and those?:

void foo(char* str) { assert (!(str+strlen(str))}
void bar(char* str) { assert (! str[strlen(str)]); }
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
vesii
  • 2,760
  • 4
  • 25
  • 71
  • 5
    Your book isn't very good. You're right, `str+strlen(str)` pretty much can't be NULL, that's sort of like saying `assert(1 + 1 != 3)`. And for a valid string, `str[strlen(str)]` is guaranteed to be the null character, `'\0'`, although that's *not* the same as a `NULL` pointer constant, so this is even more confused. – Steve Summit Aug 30 '19 at 09:41
  • See [this question](https://stackoverflow.com/questions/8114008) for some better advice on using `assert`. – Steve Summit Aug 30 '19 at 09:45
  • 1
    This may be considered nitpicking but "checking impossible cases" are not what asserts are for. If the case is impossible, there is no need for checking it. For instances you would never make an assert checking that an unsigned int is >= zero. Asserts are for checking possible but invalid/illegal cases. – Support Ukraine Aug 30 '19 at 09:48
  • 3
    Get another book... – Macmade Aug 30 '19 at 10:01
  • 1

3 Answers3

3

The second one is kind of strange. I think what your book might have been trying to show is that all c strings need to end in a null/zero character. However, the way strlen works is that it will keep scanning the string until it finds a null character. Therefore in the seconds case it will either find a null character or you will get a segmentation fault when it reads invalid memory and your program will crash. So basically there is no point to the assert because it will either pass or the program will crash.

Actually the first one suffers from the same problem as well. Because even if a null pointer is passed to foo the strlen of a null pointer will likely result in a crash. It would make more sense to assert(str != NULL).

chasep255
  • 11,745
  • 8
  • 58
  • 115
2

Neither expression makes sense.

In the first expression

assert ((str+strlen(str)) != NULL);

there is a check whether the address of the terminating zero character '\0' of a string is equal to NULL. It is evident that it is always unequal to NULL.

From the C Standard (6.5.6 Additive operators)

  1. ... In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of the array object, provided they exist.

In the second expression

assert (str[strlen(str)] != NULL)

there is a check whether the terminating zero character '\0' is equal to a null-pointer. This also does not make sense.

Pay attention to that the above expression is equivalent to the following expression

assert (*(str+strlen(str)) != NULL);

and hence also does not make sense.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1
void foo(char* str) { assert ((str+strlen(str)) != NULL); }

is legal C-code but the expression (str+strlen(str)) != NULL will always be true so there is no point in making an assert.

void bar(char* str) { assert (str[strlen(str)] != NULL); }

is comparing a pointer with a char (aka interger type). That makes no sense.

void foo(char* str) { assert (!(str+strlen(str)));}

is the same as the first foo (notice that I fixed the syntax error)

void bar(char* str) { assert (! str[strlen(str)]); }

is different from the first bar. This is legal code. It is the same as assert (str[strlen(str)] == 0);. However, it makes no sense to have this assert as it can never fail.

Notice that asserts are not for checking something that are impossible! Asserts are for checking something that are possible but invalid/illegal.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63