Why does the same not hold for an integer constant literal? Does it
not also have static storage duration?
Integer constants are not "literals" in the standard's terminology. "Constants" are a separate thing. And no, constants do not have static storage duration because they are not objects at all. They are constants. C does not define them to have storage of any kind. In practice, they usually are directly represented in the generated executable code, not among the program's data.
If I attempt to assign to an
integer constant, gcc complains that it is not an lvalue.
It isn't. In other words, a constant does not correspond to a memory location, it's just a constant.
Why are string literals given this special treatment? (And compound
literals in C99).
The treatment of string and compound literals is not special, it's just what it is. You seem to be getting confused by incorrectly considering these kinds of object literals to be a similar kind of thing to constants, but they are not. String and compound literals represent objects that do have representations as data in memory.
I've heard the following definition for lvalues: "An
lvalue (locator value) represents an object that occupies some
identifiable location in memory (i.e. has an address)."
Yes.
If a string
literal (a character array type) must be addressable in memory, why
does the same not apply to an integer?
You are again glancing off the point. Integers can and often do have addressable locations in memory. But integer constants do not (or at least, C does not require them to have). Their representations in a program are typically in executable code.
Part of the significance of the term "literal" is that the entity so described represents an actual object of the specified type.
A "constant", on the other hand, represents a value of the specified type.
Even an integer still has to be
allocated in the program's address space.
There is a somewhat subtle distinction here, but an important one, between objects and values. Objects are identified with storage locations; they have and / or contain values. Thus, an object of integer type indeed does have storage, and an expression that designates that storage is an lvalue. On the other hand, although a particular integer value may in fact be the value of any number of objects, but the value itself is not inherently associated with a specific storage location.
Is there a performance
reason?
Fundamentally, there are language design reasons. Some of these do promote better performance -- i.e. values can be encoded directly into executable machine code, rather than the machine code having to load them from (other) memory -- but I don't take those to be the primary factor.