A filename is an entry in a directory. In essence, directories are two-column tables, where column 1 is the filename and column 2 is the inode number. (Ok, for modern filesystems the story is more complex, but for the explanation that will do.) The inode number points into the inode table; this table is not visible to userland processes, but you can query an inode by calling the
lstat() system call. The inode contains the meta data of a file, such as ownership, access permissions, access, modification and change times, and so on. Most important, the inode contains or points to the information where to find the file on disk.
Another important entry is the link count, for it is possible to point to the inode from many places - these are called hardlinks. If you delete a file using
rm (that is, using the
unlink() system call), then only the entry from the directory is removed and the link count of the inode is decremented. Only if it reaches 0 the disk space associated with the inode and the inode itself is freed for further reuse.
So: a filename is a string, and the pointing happens through the data structure of the directory.
A hard link cannot link to a file on a different file system, while a soft link can. Is it because a filename pointer cannot point to an inode on a different file system, while a pointer stored in an inode can point to a file content on a differnt file system?
Each file system has its own inode table. Entries in the inode table can refer strictly only to "their own" file system. Therefore, a hardlink cannot cross filesystem boundaries.
A softlink is a very different thing. In essence it's a small file that contains a filename. If a process opens a symlink, the system follows it and opens the file referred to by that filename. Since softlinks are based solely on pathnames, they are not restricted to filesystem boundaries.