In a procedural language like C, when you call a function, that functions pointer is placed on the stack and the execution pointer jumps to it immediately. In objective-c, when you call a function you place your request to call a function onto the runtime queue. Later the runtime will pop your request and do the actual call. The asynchronous nature of this operation is the key difference.
why this is good and how it could be bad ?
One way it can be good is because we can alter the destination of a message at runtime by switching the implementations, a drawback to messaging is that adds a bit of overhead to every call — doing it a lot in a tight loop can degrade the performance of your app.