In computer science, a function or expression is said to have a side
effect if it modifies some state or has an observable interaction with
calling functions or the outside world.
From Wikipedia - Side Effect
A function, in the mathematical sense, is a mapping from input to output. The intended effect of calling a function is for it to map the input to the output it returns. If the function does anything else, it doesn't matter what, but if it has any behavior that is not mapping the input to the output, that behavior is known to be a side effect.
In more general term, a side effect is any effect which is not the intended effect of the designer of the construct.
An effect is anything that affects an actor. If I call a function that sends my girlfriend a breakup text message, that affects a bunch of actors, me, her, the cell phone company's network, etc. The only intended effect of calling a side-effect free function, is for the function to return me a mapping from my input. So for:
public void SendBreakupTextMessage() {
Messaging.send("I'm breaking up with you!")
}
If this is intended to be a function, then the only thing it should do is return void. If it was side-effect free, it should not actually send the text message.
In most programming language, there is no construct for a mathematical function. No construct is intended to be used as such. That's why most languages say you have methods or procedures. By design, those are intended to be able to do many more effects. In common programming parlance, no one really cares about the intent of what a method or a procedure was, so when someone says this function has side-effect, they effectively mean, this construct does not behave like a mathematical function. And when someone says this function is side-effect free, they mean, this construct effectively behaves like a mathematical function.
A pure function is always side effect free, by definition. A pure function, is a way to say, this function, even though it's using a construct that allows more effects, only has as effect an equal one to that of a mathematical function.
I challenge anyone to tell me when a side-effect free function would not be pure. Unless the primary intended effect of the context of the sentence using the term pure and side effect free are not that of the mathematical intended effect of a function, then those are always equal.
As such, sometimes, though more rarely, and I believe this is the distinction lacking and also misguiding people (as that is not the most common assumption) in the accepted answer, but sometimes it is assumed that the intended effect of a programming function is to map input to output, where input is not constrained to the explicit parameters of the function, but output is constrained to the explicit return value. If you assume that is the intended effect, then a function reading a file and returning a different result based on what is in the file is still side-effect free, as you allowed inputs to come from other places in your intended effect.
So, why is this all important?
It's all about control and keeping it. If you call a function, and it does something else then return a value, it is hard to reason about its behavior. You will need to go look inside the function for the actual code to guess what it is doing and assert its correctness. The ideal situation, is that it is very clear and easy to know what is the input the function is using and that it isn't doing anything else then returning an output for it. You can relax this a little, and say that knowing exactly what input it is using isn't as helpful as being certain it is not doing anything else you might not be aware of then returning a value, so maybe you are satisfied with only enforcing that it doesn't do anything else then map input, no matter where it gets it from, to output.
In almost all cases, the point of a program is to have effects other then mapping things going in to things coming out. The idea of controlling the side-effect is that you can organize code in a way that is easier to understand and reason about. If you put all the side effect together, in a place that is very explicit and central, it's easy to know where to look and trust that this is all that's happening, no more. If you have the input be very explicit too, it helps test the behavior for different input, and it's easier to use, since you don't need to change the input in a lot of different places, some which might not be obvious, just to get what you want.
Because the most helpful to understand, reason and control the behavior of a program is to have all input clearly grouped together and explicit, as well as have all side-effect be grouped together and explicit, this is generally what people talk about when they say side-effect, pure, etc.
Because the most helpful is the grouping of the side-effects and their explicitness, sometimes people will only mean that, and distinguish it by saying it is not pure, but still "side-effect" free. But side-effect is relative to the assumed "intended primary effect", so it's a contextual term. This I find is less often used, though surprisingly it is talked about a lot in this thread.
Finally, idempotent means calling this function many times with the same inputs (doesn't matter where they come from) will always result in the same effects (side effect or not).