grep sees a command line argument, that argument is parsed by the shell. For the shell,
* is a wildcard for "all non-dot files in the current directory". Since the shell handles the argument first, your line gets turned into this:
cat abcd | grep abcd otherfile zfile
(assuming that those three files reside in your current directory). This is what
grep gets to see of its arguments, but it's not what you want.
Instead, you could put the pattern for
grep in quotation marks, so that it is not processed by the shell:
cat abcd | grep "*"
That's better, but still not what you want:
grep uses regular expressions, not shell-style wildcarding. The asterisk, for
grep, means "0..n repetitions of the previous character" - a character you did not specify. Close, but no cigar.
If you want an "any" pattern, you are looking for "0..n repetitions of an arbitrary character". The latter is represented by the period (
'.') in regular expressions:
cat abcd | grep ".*"
That is what you were looking for.
Edit: The other case is more easily explained. With
grep "" you are looking for an empty string, which is present as a substring in any string.