At its root I believe you're asking a style question, which means you're unlikely to get a definitive answer. Opinions on style are, well, opinions.
Some people believe that you should use C's "natural" types — char
, short
, int
, long
, and their unsigned
variants — most of the time, and that you should use exact-size types like int32_t
only when you absolutely have to.
Some people believe that the variability implied by the "natural" types is an unrelenting source of bugs, and they believe that you should use exact-size types always.
Now, with that said, the specific case of writing
int32_t main(int32_t argc, int8_t *argv[])
is objectively wrong, for at least three reasons:
- On a platform where type
int
is 16 bits, this wrongly declares main
's return type, and the type of the argc
argument, as a 32-bit type.
- On a platform where type
char
is unsigned, this wrongly declares argv
as an array of signed character pointers. That's probably what gcc was complaining about for you.
- On a more philosophical level,
main
is not a function whose function signature you get to pick. Somebody else declared main
, somebody else is calling main
, your job is only to provide a definition for main
. So you simply have to use the types somebody else specified, even if your rule is that you want to use exact-size types whenever you can. Here, you can't.
Bottom line: Please use one of these two (equivalent) forms for main
with arguments:
int main(int argc, char *argv[])
int main(int argc, char **argv)
Unless you're writing "freestanding" code, anything else is confusing, misleading, nonstandard, or wrong. (It's also acceptable to define a main
that takes no arguments.)
What is the best practice to use int8_t?
I would say, when you really, really need a tiny, 8-bit, signed integer, or perhaps when you're manipulating memory as signed bytes. But I would not go using int8_t
instead of char
everywhere, because it's going to cause you lots of problems, and it's not going to buy you anything.