No, 31 means 31.
However, you can do some trickery. Set the job to run on any day which could potentially be the last day of the month (ie 28-31 in the day-of-month field), and then replace your command with a shell expression comprising a test on the date guarding the command:
0 0 28-31 * * [ "date +%m" != "date --date=tomorrow +%m" ] && command
The expression inside the test brackets just asks if the month number today is different to the month number tomorrow, which of course will only be true on the last day of the month. Note that the form of this expression depends on your local date - you may need to tweak it if you don't have the current GNU version.
I should say that i didn't invent this - i found it with a quick google (which the original poster should have done himself, bad poster!) in a mailing list post by a Matthew Jarvis. I would imagine this is very much a standard old unix wizard's trick, though.