Michael Haggerty <mhag...@alum.mit.edu> writes:

> If you pass a newly-initialized or newly-cleared `string_list` to
> `for_each_string_list_item()`, then the latter does
>
>     for (
>             item = (list)->items; /* note, this is NULL */
>             item < (list)->items + (list)->nr; /* note: NULL + 0 */
>             ++item)
>
> Even though this probably works almost everywhere, it is undefined
> behavior, and it could plausibly cause highly-optimizing compilers to
> misbehave.
> ...
> It would be a pain to have to change the signature of this macro, and
> we'd prefer not to add overhead to each iteration of the loop. So
> instead, whenever `list->items` is NULL, initialize `item` to point at
> a dummy `string_list_item` created for the purpose.
> ...
> -#define for_each_string_list_item(item,list) \
> -     for (item = (list)->items; item < (list)->items + (list)->nr; ++item)
> +extern struct string_list_item dummy_string_list_item;
> +#define for_each_string_list_item(item,list)                                 
> \
> +     for (item = (list)->items ? (list)->items : &dummy_string_list_item; \
> +          item < (list)->items + (list)->nr;                              \
> +          ++item)

Sorry, but I am confused.

So when (list)->items is NULL, the loop termination condition that
used to be

        NULL < NULL + 0

that was problematic because NULL + 0 is problematic now becomes

        &dummy < NULL + 0

in the new code?  What made NULL + 0 not problematic now?

Reply via email to