Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to printf() getpid() ? (Some versions of gcc make this difficult)

3,659 views
Skip to first unread message

Kenny McCormack

unread,
Apr 28, 2001, 8:53:59 PM4/28/01
to
Under certain versions of gcc, the following lines causes an error if
compiling with "-Wall -Werror":

printf("My pid is %d\n",getpid());

The problem is that getpid() is pid_t, and there's no printf conversion
character for pid_t's. It complains that it is an int format and a pid_t
arg.

To fix it, you have to do: (int) getpid()

I'm curious as to:
1) Who's at fault for this?
2) Is there a general solution to the problem of there not being
printf conversion characters for other than the standard types?

Juergen Heinzl

unread,
Apr 28, 2001, 9:46:08 PM4/28/01
to
In article <9cfon7$qog$1...@yin.interaccess.com>, Kenny McCormack wrote:
>Under certain versions of gcc, the following lines causes an error if
>compiling with "-Wall -Werror":
>
> printf("My pid is %d\n",getpid());
>
>The problem is that getpid() is pid_t, and there's no printf conversion
>character for pid_t's. It complains that it is an int format and a pid_t
>arg.
>
>To fix it, you have to do: (int) getpid()
>
>I'm curious as to:
> 1) Who's at fault for this?
[-]
It's no-ones fault. Everbody and his brother can create a typedef
and printf() just can't know of all types. Mind getpid() is available
in Unix but C, and so it's library functions, are available for
many other systems, too.

> 2) Is there a general solution to the problem of there not being
> printf conversion characters for other than the standard types?

[-]
Sure, cast it to a standard type ;) I'd prefer an unsigned though, read
unsigned long as a process id is never going to be negative.

Ta',
Juergen

--
\ Real name : Juergen Heinzl \ no flames /
\ EMail Private : jue...@monocerus.demon.co.uk \ send money instead /

Kenny McCormack

unread,
Apr 28, 2001, 10:58:25 PM4/28/01
to
In article <slrn9emsio...@monocerus.demon.co.uk>,
Juergen Heinzl <jue...@monocerus.demon.co.uk> wrote:
...

>> 2) Is there a general solution to the problem of there not being
>> printf conversion characters for other than the standard types?
>[-]
>Sure, cast it to a standard type ;) I'd prefer an unsigned though, read
>unsigned long as a process id is never going to be negative.

The problem is this. The following principles are inconsistent with each
other:
1) The compiler is correctly implemented (bug free) (*)
2) Your code should always compile without any warnings (I.e.,
it should be lint-free)
3) Having non-standard types for ordinary things (I.e., pid_t when
everybody knows it's really an int) is a good thing.

(*) In case this is unclear, my point here is that the compiler is correct
in issuing a warning for this sort of thing.

I note, BTW, that only some versions/implementations of GCC flag this one,
so it may be that assumption #1 is the flawed assumption.

Michael

unread,
Apr 29, 2001, 12:10:19 AM4/29/01
to
In article <9cfon7$qog$1...@yin.interaccess.com>, Kenny McCormack wrote:
> Under certain versions of gcc, the following lines causes an error if
> compiling with "-Wall -Werror":
>
> printf("My pid is %d\n",getpid());
>
> The problem is that getpid() is pid_t, and there's no printf conversion
> character for pid_t's. It complains that it is an int format and a pid_t
> arg.

No errors here.

$ cat test.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int
main()
{


printf("My pid is %d\n", getpid());

return 0;
}
$ gcc -Wall -ansi -pedantic test.c
$ ./a.out
My pid is 37606
$ gcc -v
Reading specs from /home/graywane/atl/lib/gcc-lib/i386-unknown-freebsd4.3/3.0/specs
Configured with: /home/graywane/work/gcc/configure --prefix=/home/graywane/atl --disable-shared --disable-nls
gcc version 3.0 20010406 (prerelease)

--
Note: There is no example in my hostname.

Juergen Heinzl

unread,
Apr 29, 2001, 3:55:29 PM4/29/01
to
[-]
If pid_t is an int you'd be right as a typedef does not create a new
type and the compiler should not generate a warning. Given pid_t is
an int and you consider the warning to be bogus, then yes, so do I in
this case.

Kenny McCormack

unread,
Apr 29, 2001, 8:47:13 PM4/29/01
to
In article <slrn9eoscu...@monocerus.demon.co.uk>,

Juergen Heinzl <jue...@monocerus.demon.co.uk> wrote:
>>The problem is this. The following principles are inconsistent with each
>>other:
>> 1) The compiler is correctly implemented (bug free) (*)
>> 2) Your code should always compile without any warnings (I.e.,
>> it should be lint-free)
>> 3) Having non-standard types for ordinary things (I.e., pid_t when
>> everybody knows it's really an int) is a good thing.
>>
>>(*) In case this is unclear, my point here is that the compiler is correct
>>in issuing a warning for this sort of thing.
>>
>>I note, BTW, that only some versions/implementations of GCC flag this one,
>>so it may be that assumption #1 is the flawed assumption.
>[-]
>If pid_t is an int you'd be right as a typedef does not create a new
>type and the compiler should not generate a warning. Given pid_t is
>an int and you consider the warning to be bogus, then yes, so do I in
>this case.

Aha! In fact, I just figured out what the problem is. pid_t is, on the
system in question, (typedef'd to) long, thus the compiler flags this as an
error (warning). Comments:

1) FWIW, ints and longs are both 32 bits on this system, so the
whole thing ought to be moot.
2) Its pretty stupid to make pid_t long - I think the most rational
choice would be "unsigned int" (as you allude to above).
3) Pids never get larger than about 30,000 anyway (at least on any
Unix system I've ever seen), so a (signed) short is really enough.
4) The real underlying problem here is that you can't write
portable, lint-free code. In one form or another, this bugaboo
could pop up anywhere. And note that casting the result
(getpid()) to int can't be the right solution - as is the case
with most instances of casting, it is a kludge - and it could
actually be a problem on a system where ints and pid_ts really
were different sizes.

The only really correct solution is to delve into the include files on the
affected system, figure out what a pid_t is, and then change the printf
format specifier accordingly (via appropriate #ifdefs, of course).

But doesn't that just seem like more trouble than it is worth???

Juergen Heinzl

unread,
Apr 30, 2001, 5:46:59 PM4/30/01
to
In article <9cicmh$9gd$1...@yin.interaccess.com>, Kenny McCormack wrote:
>In article <slrn9eoscu...@monocerus.demon.co.uk>,
>Juergen Heinzl <jue...@monocerus.demon.co.uk> wrote:
>>>The problem is this. The following principles are inconsistent with each
>>>other:
>>> 1) The compiler is correctly implemented (bug free) (*)
>>> 2) Your code should always compile without any warnings (I.e.,
>>> it should be lint-free)
>>> 3) Having non-standard types for ordinary things (I.e., pid_t when
>>> everybody knows it's really an int) is a good thing.
>>>
>>>(*) In case this is unclear, my point here is that the compiler is correct
>>>in issuing a warning for this sort of thing.
>>>
>>>I note, BTW, that only some versions/implementations of GCC flag this one,
>>>so it may be that assumption #1 is the flawed assumption.
>>[-]
>>If pid_t is an int you'd be right as a typedef does not create a new
>>type and the compiler should not generate a warning. Given pid_t is
>>an int and you consider the warning to be bogus, then yes, so do I in
>>this case.
>
>Aha! In fact, I just figured out what the problem is. pid_t is, on the
>system in question, (typedef'd to) long, thus the compiler flags this as an
>error (warning). Comments:
>
> 1) FWIW, ints and longs are both 32 bits on this system, so the
> whole thing ought to be moot.
[-]
Aehm .. no, as int and long are distinct base types.

> 2) Its pretty stupid to make pid_t long - I think the most rational
> choice would be "unsigned int" (as you allude to above).

[-]
Maybe you're using a system which is available for 64 bit architectures, too ?
It might explain the usage of long to stay consistent. Just an idea, sure.

> 3) Pids never get larger than about 30,000 anyway (at least on any
> Unix system I've ever seen), so a (signed) short is really enough.

[-]
Well, better safe than sorry ;)

> 4) The real underlying problem here is that you can't write
> portable, lint-free code. In one form or another, this bugaboo
> could pop up anywhere. And note that casting the result
> (getpid()) to int can't be the right solution - as is the case
> with most instances of casting, it is a kludge - and it could
> actually be a problem on a system where ints and pid_ts really
> were different sizes.

[-]
Yes. It's why I wrote use unsigned long since then you're probably on
the safe side. Of course some time in the future systems may require
long long's for process ID's, though I'm being hopeful to spend my
penison on some isle in the South Sea by then (it ought to buy me
a drink or two at least .. I hope).

>The only really correct solution is to delve into the include files on the
>affected system, figure out what a pid_t is, and then change the printf
>format specifier accordingly (via appropriate #ifdefs, of course).
>
>But doesn't that just seem like more trouble than it is worth???

[-]
I'd prefer the cast, though not to a signed int for it's legal, less
hassle and I try not to know what's behind a typedef; there're just
to many. Why bother when keeping it it simple and stupid does the job ?

Kenny McCormack

unread,
Apr 30, 2001, 7:01:11 PM4/30/01
to
In article <slrn9ern8q...@monocerus.demon.co.uk>,
Juergen Heinzl <jue...@monocerus.demon.co.uk> wrote:
...

>>The only really correct solution is to delve into the include files on the
>>affected system, figure out what a pid_t is, and then change the printf
>>format specifier accordingly (via appropriate #ifdefs, of course).
>>
>>But doesn't that just seem like more trouble than it is worth???
>[-]
>I'd prefer the cast, though not to a signed int for it's legal, less
>hassle and I try not to know what's behind a typedef; there're just
>to many. Why bother when keeping it it simple and stupid does the job ?

But that would be *wrong* under the following conditions:

1) You're on a system where pid_t is long
2) sizeof(long) > sizeof(int) (Say, for arg, that 64 > 32)
3) A pid was actually greater than 4GB.

The printf would print only the low order 32 bits.

Sebastian Hans

unread,
May 2, 2001, 7:50:58 AM5/2/01
to

Then why not printf("My pid is %ld\n", (unsigned long) getpid()); ?

Cheers
seb
--

/ sebastian seb hans \ www.crosswinds.net/~sebh / attention this msg \
| student of comp sci \ yes is no and no is ns / will destroy itself |
\ techn univ of munich \ ha...@in.tum.de / in one second .. rip /

Kenny McCormack

unread,
May 2, 2001, 7:00:41 PM5/2/01
to
In article <3AEFF4A2...@informatik.tu-muenchen.de>,

Sebastian Hans <ha...@informatik.tu-muenchen.de> wrote:
>Kenny McCormack wrote:
>>
>> In article <slrn9ern8q...@monocerus.demon.co.uk>,
>> Juergen Heinzl <jue...@monocerus.demon.co.uk> wrote:
>> >I'd prefer the cast, though not to a signed int for it's legal, less
>> >hassle and I try not to know what's behind a typedef; there're just
>> >to many. Why bother when keeping it it simple and stupid does the job ?
>>
>> But that would be *wrong* under the following conditions:
>>
>> 1) You're on a system where pid_t is long
>> 2) sizeof(long) > sizeof(int) (Say, for arg, that 64 > 32)
>> 3) A pid was actually greater than 4GB.
>>
>> The printf would print only the low order 32 bits.
>
>Then why not printf("My pid is %ld\n", (unsigned long) getpid()); ?

Because in order to know that, you'd have had to delve into the include
files on the system in question. The point of this thread is not that it
can't be done, but rather that doing so requires monkeying around with
details that should not be user visible (i.e., you should not ever have to
look inside the include files).

Juergen Heinzl

unread,
May 3, 2001, 4:54:57 PM5/3/01
to
In article <9cq3ip$r6t$1...@yin.interaccess.com>, Kenny McCormack wrote:
>In article <3AEFF4A2...@informatik.tu-muenchen.de>,
>Sebastian Hans <ha...@informatik.tu-muenchen.de> wrote:
>>Kenny McCormack wrote:
>>>
>>> In article <slrn9ern8q...@monocerus.demon.co.uk>,
>>> Juergen Heinzl <jue...@monocerus.demon.co.uk> wrote:
>>> >I'd prefer the cast, though not to a signed int for it's legal, less
>>> >hassle and I try not to know what's behind a typedef; there're just
>>> >to many. Why bother when keeping it it simple and stupid does the job ?
>>>
>>> But that would be *wrong* under the following conditions:
>>>
>>> 1) You're on a system where pid_t is long
[-]
Yes. It's why I said use an unsigned long.

>>> 2) sizeof(long) > sizeof(int) (Say, for arg, that 64 > 32)
>>> 3) A pid was actually greater than 4GB.

[-]
Yes, if sizeof( pid_t ) > sizeof( unsigned long ) you're toast, but
how realistic is this ? Still if it bothers you and yes, I know many
applications out there were never meant to run around 2000, you can
still guard against it using some #if ... #endif construct.

>>> The printf would print only the low order 32 bits.
>>
>>Then why not printf("My pid is %ld\n", (unsigned long) getpid()); ?
>
>Because in order to know that, you'd have had to delve into the include
>files on the system in question. The point of this thread is not that it
>can't be done, but rather that doing so requires monkeying around with
>details that should not be user visible (i.e., you should not ever have to
>look inside the include files).

[-]
No and BTW %lu, not %ld. Using (unsigned long)getpid() is going to work
as pid_t is an integral type, see the Unix98 specification and as long
as its size is less or equal to the one of an unsigned long.

Since pid_t is not an intrinsic type but a typedef it *can't* be larger
than one.

C++ knows of long long now, but whether this is the case in the latest
C standard .. not sure as for the later I haven't got the last and
official version. Still if so, then the solution is obvious, isn't it ?

Juergen Heinzl

unread,
May 3, 2001, 5:29:18 PM5/3/01
to
In article <slrn9f3h91...@monocerus.demon.co.uk>, Juergen Heinzl wrote:
>In article <9cq3ip$r6t$1...@yin.interaccess.com>, Kenny McCormack wrote:
>>In article <3AEFF4A2...@informatik.tu-muenchen.de>,
>>Sebastian Hans <ha...@informatik.tu-muenchen.de> wrote:
>>>Kenny McCormack wrote:
>>>>
>>>> In article <slrn9ern8q...@monocerus.demon.co.uk>,
>>>> Juergen Heinzl <jue...@monocerus.demon.co.uk> wrote:
>>>> >I'd prefer the cast, though not to a signed int for it's legal, less
>>>> >hassle and I try not to know what's behind a typedef; there're just
>>>> >to many. Why bother when keeping it it simple and stupid does the job ?
>>>>
>>>> But that would be *wrong* under the following conditions:
>>>>
>>>> 1) You're on a system where pid_t is long
>[-]
>Yes. It's why I said use an unsigned long.
[-]
Have to correct myself 8-}

Unix98 defines pid_t as a *signed* integral type, actually. Makes sense
of course as eg. fork() needs to be able to return -1.

Sorry,

0 new messages