They have the same semantics.
The constant 999 is of type int .
int i=999; char c=i;
i , created as an object of type int and initialized to int 999 , with obvious semantics.
c is created as an object of type char and initialized to i , which turns out to be 999 . This value is implicitly converted from int to char .
The plain char is determined by the implementation.
If plain char is an unsigned type, the result of the conversion is correctly defined. The value decreases modulo CHAR_MAX+1 . For a typical implementation with 8-bit bytes ( CHAR_BIT==8 ), CHAR_MAX+1 will be 256, and the stored value will be 999 % 256 or 231 .
If a plain char is a signed type and 999 exceeds CHAR_MAX , the conversion gives the result defined by the implementation (or, starting with C99, raises the signal defined by the implementation, but I don't know any implementations that do this). As a rule, for a system with a 2'-complement with CHAR_BIT==8 result will be -25 .
char c=999;
c is created as an object of type char . Its initial value is the value of int 999 , converted to char - exactly the same rules as I described above.
If CHAR_MAX >= 999 (which can only happen if CHAR_BIT , the number of bits in a byte is at least 10), then the conversion is trivial. There are C implementations for DSPs (digital signal processors) with CHAR_BIT set to, for example, 32. This is not something you are likely to encounter with most systems.
Most likely, you will receive a warning in the second case, because it converts a constant expression; in the first case, the compiler may not keep track of the expected value of i . But a smart enough compiler could warn about both, and a naive (but still completely appropriate) compiler could not warn about it.
As I said above, the result of converting a value to a signed type when the original value does not match the target type is determined by the implementation. I believe it is possible that an implementation can define different rules for constant and non-constant expressions. However, this would be a perverse choice; I'm not sure what the DS9K does.
As for the reference comment “The first is the assignment, the second is the initialization”, this is not true. Both initialization; there are no assignments in both code snippets. There is a difference in the fact that this is initialization with a constant value, and the other is not. This implies, by the way, that the second fragment can be displayed in the file area outside any function, while the first could not.