Unfortunately, the behavior is a little more tricky than suggested. In particular, the problem arises when using commands that cause double evaluation, such as /scid, /scon, /timer, and /flash. (Are there any others?)

Suppose you have the channel name stored inside $chan which would be a fairly common situation. As already mentioned, escaping it once can solve the problem. For example:

scid 43 msg $!chan hello

This would work because $!chan evalutes to $chan during the first evaluation, and $chan evalutes to the channel name during the second evaluation. It's critical to note that $chan is still a valid identifier when the second evaluation occurs. So, this method should work.

Timers are a more difficult problem to solve, however. The second evaluation occurs when $chan will no longer be retrievable. This means you MUST retrieve it during the first evaluation, but then it becomes more difficult to prevent the second evaluation from destroying # as a channel name.

For timers, this should solve the problem, although I suspect there might be a less confusing way that I can't think of right now:

timer 1 3 msg $!right(: $+ $chan $+ ,-1) hello!

I know your question didn't specifically deal with timers, but you'll likely run into the problem if you are dealing with the channel # in an mIRC script, so I thought it was relevant to point it out.