What is a file descriptor? Why do we need them?
A file descriptor is a number that represents an open file in a process. It's a way for the program to remember which file it's manipulating. Opening a file looks for a free number and assigns it to the file in that process's file descriptor table; closing the file removes the entry from the process's descriptor table. There is no relation between file descriptor n in a process and the file descriptor with the same number in another process.
“Every file has three of them (stdin, stdout, stderr)” is nonsense. Processes have file descriptors, not files. Processes can and often do have more than three file descriptors, and can have fewer. Stdin, stdout and stderr are the names for file descriptors 0, 1 and 2 because they have a conventional meaning: stdin (standard input) is where the program is supposed to read user input (if it wants to), stdout (standard output) is where the program is supposed to write the data that it produces (if it wants to), and stderr (standard error) is for error messages. Stdin and stdout are of use in programs intended to be used on the command lines and especially in pipelines; I invite you to read what is meant by connecting STDOUT and STDIN? and (more advanced) How can a command have more than one output?
They are represented by an int
Yes, they are numbered starting from zero, which is a common and straightforward means of accounting for unique items of a similar kind. Kind of like sports jerseys. E.g., there may be several goalies on a team, but you know which one is in play at any given point because each member of the team has a unique number. That's the only significance.
what is a file descriptor?
It refers to an input/output conduit. Usually they are only one or the other, but they maybe both.
Every file has three of them
Generally every process has at least three of them, this is a feature of *nix style OS's.
Why do we need them?
You don't need them, unless you want to do input/output to something other than the current process. However, the "you" in such a process would be abstract in the sense of "I wrote this", since no one including you else is ever likely to make meaningful use of it. Processes do not exist in a void, they are entities managed by the operating system, and need to interact with other entities, access files, hardware devices, etc. Files descriptors are a fundamental means of doing so.
Why can't I just say hey I want to write to stdin, or to stdout?
Depending on context you can, obviously. In C these are (ostensibly) macros that lead back to the corresponding low level descriptor (have a look in
stdio.h...). If it bugs you WRT the shell, you could always, e.g.:
export stdin=0 export stdout=1
Although this is probably not a very good idea, since you risk getting stomped on in the global namespace in some possibly unfortunate ways. Also,
stdin takes longer to type than