This type question and discussion is always a challenge, because it requires the interpretation of the C-standard, which in many aspects, isn't written for clarity, but is more the result of deliberation and compromise between what two (or more) competing factions will agree to include in it. After having gone through it a number of times, it is clear that far more discussion went into what to, or not to, include than ever went into where or how to include it in the standard for readability.
Continuing from the comments, I think we all can agree, based on the number of times it has been referenced in the comments and answers, that C11 Standard (draft n1570) § 6.3.2.1 Lvalues, arrays, and function designators (¶2)) applies.
"If the lvalue designates an object of automatic storage
duration that could have been declared with the register storage
class (never had its address taken), and that object is
uninitialized (not declared with an initializer and no assignment to
it has been performed prior to use), the behavior is undefined."
(emphasis mine)
The issue becomes, "Is an array with automatic storage something that could have been declared with the register storage class?"
At first look, the obvious thought is "An array with a register storage-class specifier? That would be pretty dumb, you can't take the address, how would you ever access the values?" Given § 6.2.5 Types (comment 36)) "The address of such an object is taken implicitly when an array member is accessed."
First thoughts are often wrong, because arrays with automatic storage allow the use of the register storage class. § 6.7.1 (6 & comment 121)
The following code is perfectly legal -- while arguably not that useful.
#include <stdio.h>
int main (void) {
register int a[] = { 1, 2, 3, 4 };
register size_t n = sizeof a / sizeof (int);
printf ("n : %zu\n", n);
return 0;
}
The only operators that can be applied to an array declared with storage-class specifier register are sizeof
and _Alignof
. (See § 6.7.1 (comment 121)
Given the above, and given any uninitialized element in the array "is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined."
In your specific case:
char c = output[1]; // accesses something "uninitialized"; But is it UB?
output[1]
designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.