I'm not 100% sure about this, but I suspect that you are seeing the result of a compiler optimization. The "const" is telling the compiler that the value of j won't be changing. On the other hand, you bypass that assumption by trying to sneak a new value into j's memory address. j's address does indeed contain 110 at run time, but when the print statement comes along, the compiler assumes that j is still 18 (that's what you told it to assume with the const) and doesn't bother to reference j's memory location at all - it just loads 18 using an immediate operand with a value of 18.
The immediate reference may need some clarification if you've never coded in assembly. There are at least 2 ways to load numeric values. The first, and most versatile, is to use an assembler instruction that loads a value from memory. In this case, the address of the value is embedded in the machine code for the instruction that loads the value. In most cases this will be a 32 bit pointer. In the second case, the value itself is coded directly into the machine code. The length of this so called immediate operand may be 1, 2, 4, or 8 bytes. Immediate loads are almost always more efficient, both in terms of memory utilization and speed. In your case, the compiler will be able to code the constant in 1 byte (and then sign extend it to 32 bits) and the job is done as soon as the instruction is loaded. A memory reference would require a 32 bit address load (3 extra bytes) followed by the operand (also 32 bits). In total 7 extra bytes to load.