The first one, in global scope, is an example for a so called Tentative definition.
A tentative definition is an external declaration without an initializer, and either without a storage-class specifier or with the specifier static.
A tentative definition is a declaration that may or may not act as a definition. If an actual external definition is found earlier or later in the same translation unit, then the tentative definition just acts as a declaration.
In the second example, b
has block scope and no linkage, in other words: the declarations are not external. Hence, the tentative definition rule does not apply.