Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #64771 > unrolled thread
| Started by | "Rick C. Hodgin" <rick.c.hodgin@gmail.com> |
|---|---|
| First post | 2015-07-06 09:04 -0700 |
| Last post | 2015-07-09 15:25 -0700 |
| Articles | 20 on this page of 94 — 23 participants |
Back to article view | Back to comp.lang.c
printf format specifier changes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 09:04 -0700
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-06 17:50 +0100
Re: printf format specifier changes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 11:34 -0700
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-06 19:47 +0100
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-06 19:53 +0100
Re: printf format specifier changes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-06 11:57 -0700
Re: printf format specifier changes "James Harris" <james.harris.1@gmail.com> - 2015-09-06 10:53 +0100
Re: printf format specifier changes Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-09-06 04:21 -0700
Re: printf format specifier changes Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-09-06 13:41 +0100
Re: printf format specifier changes Richard Heathfield <rjh@cpax.org.uk> - 2015-07-06 19:44 +0100
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-06 22:14 +0100
Re: printf format specifier changes Robert Wessel <robertwessel2@yahoo.com> - 2015-07-06 22:43 -0500
Re: printf format specifier changes Keith Thompson <kst-u@mib.org> - 2015-07-06 23:01 -0700
Re: printf format specifier changes glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-07-07 06:43 +0000
Re: printf format specifier changes Phil Carmody <pc+usenet@asdf.org> - 2015-07-09 10:52 +0300
Re: printf format specifier changes Richard Heathfield <rjh@cpax.org.uk> - 2015-07-09 09:26 +0100
Re: printf format specifier changes Phil Carmody <pc+usenet@asdf.org> - 2015-07-12 12:56 +0300
Re: printf format specifier changes Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-07-12 06:12 -0700
Re: printf format specifier changes Rosario19 <Ros@invalid.invalid> - 2015-07-07 10:22 +0200
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-07 10:10 +0100
Re: printf format specifier changes Philip Lantz <prl@canterey.us> - 2015-07-07 00:54 -0700
Re: printf format specifier changes Nobody <nobody@nowhere.invalid> - 2015-07-07 15:08 +0100
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-07 16:12 +0100
Re: printf format specifier changes raltbos@xs4all.nl (Richard Bos) - 2015-07-09 10:34 +0000
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-09 12:25 +0100
Re: printf format specifier changes Phil Carmody <pc+usenet@asdf.org> - 2015-07-12 13:02 +0300
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-12 11:23 +0100
Re: printf format specifier changes <william@wilbur.25thandClement.com> - 2015-07-07 11:50 -0700
Re: printf format specifier changes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-07 12:14 -0700
Re: printf format specifier changes Les Cargill <lcargill99@comcast.com> - 2015-07-07 21:52 -0500
Re: printf format specifier changes Keith Thompson <kst-u@mib.org> - 2015-07-07 20:42 -0700
Re: printf format specifier changes Phil Carmody <pc+usenet@asdf.org> - 2015-07-09 11:12 +0300
Re: printf format specifier changes Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-07-09 05:03 -0700
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-09 13:10 -0500
Re: printf format specifier changes James Kuyper <jameskuyper@verizon.net> - 2015-07-09 08:58 -0400
Re: printf format specifier changes Keith Thompson <kst-u@mib.org> - 2015-07-09 08:10 -0700
Re: printf format specifier changes Phil Carmody <pc+usenet@asdf.org> - 2015-07-12 12:58 +0300
Re: printf format specifier changes James Kuyper <jameskuyper@verizon.net> - 2015-07-12 12:57 -0400
Re: printf format specifier changes Keith Thompson <kst-u@mib.org> - 2015-07-12 11:14 -0700
Re: printf format specifier changes gazelle@shell.xmission.com (Kenny McCormack) - 2015-07-12 18:26 +0000
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-08 13:09 +0100
Re: printf format specifier changes James Kuyper <jameskuyper@verizon.net> - 2015-07-08 08:10 -0400
Re: printf format specifier changes Les Cargill <lcargill99@comcast.com> - 2015-07-08 08:12 -0500
Re: printf format specifier changes Keith Thompson <kst-u@mib.org> - 2015-07-08 08:38 -0700
Re: printf format specifier changes James Kuyper <jameskuyper@verizon.net> - 2015-07-08 12:00 -0400
Re: printf format specifier changes Les Cargill <lcargill99@comcast.com> - 2015-07-08 17:20 -0500
Re: printf format specifier changes Phil Carmody <pc+usenet@asdf.org> - 2015-07-09 11:08 +0300
Re: printf format specifier changes Phil Carmody <pc+usenet@asdf.org> - 2015-07-08 20:30 +0300
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-08 18:56 +0100
Re: printf format specifier changes gordonb.lmwiv@burditt.org (Gordon Burditt) - 2015-07-09 11:09 -0500
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-09 14:05 -0500
Re: printf format specifier changes Keith Thompson <kst-u@mib.org> - 2015-07-08 11:27 -0700
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-08 15:07 -0500
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-06 23:39 -0500
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-07 10:19 +0100
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-07 07:57 -0500
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-07 14:15 +0100
Re: printf format specifier changes Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-07 14:46 +0100
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-07 09:37 -0500
Re: printf format specifier changes Phil Carmody <pc+usenet@asdf.org> - 2015-07-09 11:24 +0300
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-09 09:55 -0500
Re: printf format specifier changes <william@wilbur.25thandClement.com> - 2015-07-09 11:53 -0700
Re: printf format specifier changes <william@wilbur.25thandClement.com> - 2015-07-09 13:48 -0700
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-09 17:01 -0500
Re: printf format specifier changes Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-07 10:59 +0100
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-07 07:48 -0500
Re: printf format specifier changes Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-07 14:30 +0100
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-07 10:05 -0500
Re: printf format specifier changes Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-07 23:16 +0100
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-07 20:29 -0500
Re: printf format specifier changes Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-07-08 00:43 -0700
Re: printf format specifier changes Robert Wessel <robertwessel2@yahoo.com> - 2015-07-09 02:29 -0500
Re: printf format specifier changes Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-09 10:34 +0100
Re: printf format specifier changes BGB <cr88192@hotmail.com> - 2015-07-09 09:35 -0500
Re: printf format specifier changes Keith Thompson <kst-u@mib.org> - 2015-07-07 08:37 -0700
Re: printf format specifier changes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-07 08:45 -0700
Re: printf format specifier changes <william@wilbur.25thandClement.com> - 2015-07-07 12:12 -0700
Re: printf format specifier changes pooja deshpande <namitadeshpande25@gmail.com> - 2015-07-09 09:29 -0700
Re: printf format specifier changes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-09 09:34 -0700
Re: printf format specifier changes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-09 09:59 -0700
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-09 22:33 +0100
Re: printf format specifier changes Keith Thompson <kst-u@mib.org> - 2015-07-09 15:17 -0700
Re: printf format specifier changes glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2015-07-10 00:30 +0000
Re: printf format specifier changes Reinhardt Behm <rbehm@hushmail.com> - 2015-07-10 09:17 +0800
Re: printf format specifier changes David Kleinecke <dkleinecke@gmail.com> - 2015-07-09 10:02 -0700
Re: printf format specifier changes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-09 10:19 -0700
Re: printf format specifier changes Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-09 21:50 +0100
Re: printf format specifier changes Keith Thompson <kst-u@mib.org> - 2015-07-09 15:05 -0700
Re: printf format specifier changes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-09 15:09 -0700
Re: printf format specifier changes Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-07-10 00:28 +0100
Re: printf format specifier changes raltbos@xs4all.nl (Richard Bos) - 2015-07-13 20:39 +0000
Re: printf format specifier changes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-09 15:07 -0700
Re: printf format specifier changes Bartc <bc@freeuk.com> - 2015-07-09 23:16 +0100
Re: printf format specifier changes "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2015-07-09 15:25 -0700
Page 3 of 5 — ← Prev page 1 2 [3] 4 5 Next page →
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-07-08 13:09 +0100 |
| Message-ID | <mnj3qp$e58$1@dont-email.me> |
| In reply to | #64890 |
On 08/07/2015 03:52, Les Cargill wrote:
> Bartc wrote:
>> In 2015, the whole notion of having to tell a compiler what it already
>> knows - the type of the values it's printing - is outdated.
>>
>
> No, it is not.
>
> Example 1:
>
> char *s = something();
>
> printf(":%s: 0x%08x\n",s,(int)s);
>
> Every. Single. Attempt. To improve on this. Fails. Repeatedly.
>
> Serialization Is Hard.
So you're printing a string followed by its hex address? Here are some
examples from other languages, all mine:
(1) println ":",s,":",hex(s)
(2) println ":",s,": 0x",ref void(s)
(3) fprintln ":#: 0x#",s,int(s):"z8h" # exact match to yours
There's probably the same amount of clutter to achieve the same result,
but much less type dependency. I don't need to tell the print routine
that s is a string, for example.
I also changed s to an int type without changing anything else. In my
examples, it still worked, but it printed the integer value. In the C
version, it now crashed. Although some compilers did warn about the
mismatch, which you may or may not notice if there are lots of warnings.
But even if you do notice, /you now have to change something else/ in
the code. And it's not going to be two-line programs such as this.
C, and apparently you as well, are mixing up format specifiers with type
specifiers. The two are different.
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-07-08 08:10 -0400 |
| Message-ID | <mnj3tm$efu$1@dont-email.me> |
| In reply to | #64890 |
On 07/07/2015 10:52 PM, Les Cargill wrote:
> Bartc wrote:
>> In 2015, the whole notion of having to tell a compiler what it already
>> knows - the type of the values it's printing - is outdated.
>>
>
> No, it is not.
>
> Example 1:
>
> char *s = something();
>
> printf(":%s: 0x%08x\n",s,(int)s);
>
> Every. Single. Attempt. To improve on this. Fails. Repeatedly.
Personally, I'd use %p and (void*)s, but I presume that you have your
reasons for avoiding it.
Attempt 1:
printf(":%s: 0x%08x\n", s, (unsigned)s);
Attempt 2:
printf(":%s: 0x%08lx\n", s, (unsigned long)s);
Attempt 3 (requires C99):
#include <inttypes.h>
#ifdef PRIxPTR
printf(":%s: 0x%08" PRIxPTR "\n", s, (uintptr_t)s);
#else
#error There is no integer type supported on this system\
that is big enough to store all the information in a char*.
#endif
Attempt 3 is by far the clumsiest, but the only one of the three that is
guaranteed to either print the full information in the pointer as an
integer, or to give you a warning if that's not possible.
--
James Kuyper
[toc] | [prev] | [next] | [standalone]
| From | Les Cargill <lcargill99@comcast.com> |
|---|---|
| Date | 2015-07-08 08:12 -0500 |
| Message-ID | <mnj7h3$qrp$1@dont-email.me> |
| In reply to | #64905 |
James Kuyper wrote:
> On 07/07/2015 10:52 PM, Les Cargill wrote:
>> Bartc wrote:
>
>>> In 2015, the whole notion of having to tell a compiler what it already
>>> knows - the type of the values it's printing - is outdated.
>>>
>>
>> No, it is not.
>>
>> Example 1:
>>
>> char *s = something();
>>
>> printf(":%s: 0x%08x\n",s,(int)s);
>>
>> Every. Single. Attempt. To improve on this. Fails. Repeatedly.
>
> Personally, I'd use %p and (void*)s, but I presume that you have your
> reasons for avoiding it.
>
Not really. I recall vaguely something unsettling with %p, but
*for now* it's not that unusual to be able to cast a pointer thru an int.
<snip>
--
Les Cargill
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-07-08 08:38 -0700 |
| Message-ID | <lnsi8yaccl.fsf@kst-u.example.com> |
| In reply to | #64907 |
Les Cargill <lcargill99@comcast.com> writes:
> James Kuyper wrote:
>> On 07/07/2015 10:52 PM, Les Cargill wrote:
[...]
>>> Example 1:
>>>
>>> char *s = something();
>>>
>>> printf(":%s: 0x%08x\n",s,(int)s);
>>>
>>> Every. Single. Attempt. To improve on this. Fails. Repeatedly.
>>
>> Personally, I'd use %p and (void*)s, but I presume that you have your
>> reasons for avoiding it.
>
> Not really. I recall vaguely something unsettling with %p, but
> *for now* it's not that unusual to be able to cast a pointer thru an int.
>
> <snip>
The format of the output produced by %p is implementation-defined.
A hexadecimal representation with a "0x" prefix is typical, but there
are systems where it's unprefixed and it could be difficult to tell
at a glance that it's a pointer. It's used mostly for debugging,
so user-friendliness isn't a huge issue. Something like "@%p"
might be clearer.
On many 64-bit systems, int (which should be unsigned int in your
example) is 32 bits and char* is 64 bits. On my system, printing
the address of a local variable with "%p" shows "0x7fffca90b597";
printing the same address by casting to unsigned int gives a
compile-time warning and prints "0xca90b597".
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-07-08 12:00 -0400 |
| Message-ID | <559D4901.1040000@verizon.net> |
| In reply to | #64907 |
On 07/08/2015 09:12 AM, Les Cargill wrote:
> James Kuyper wrote:
>> On 07/07/2015 10:52 PM, Les Cargill wrote:
...
>>> char *s = something();
>>>
>>> printf(":%s: 0x%08x\n",s,(int)s);
>>>
>>> Every. Single. Attempt. To improve on this. Fails. Repeatedly.
>>
>> Personally, I'd use %p and (void*)s, but I presume that you have your
>> reasons for avoiding it.
>>
>
> Not really. I recall vaguely something unsettling with %p, but
> *for now* it's not that unusual to be able to cast a pointer thru an int.
Well, the reason I presumed "you have your reasons" is that I can think
of a few myself. First of all, the standard does not specify the format
of the output from %p. Therefore, it could be hexadecimal, decimal, base
36, octal, or even binary. It might have "decorations" such as in
FFEF:0123 to indicate segment:offset. It needn't even have any part that
looks like a number, though I have a hard time imagining why anyone
would choose a format that didn't have number-like parts.
The single biggest issue: there's no upper limit on the length of the
output - for example, in principle it could be a decimal number written
out in English: "One billion two hundred and thirty four million five
hundred and sixty seven thousand eight hundred and ninety".
[toc] | [prev] | [next] | [standalone]
| From | Les Cargill <lcargill99@comcast.com> |
|---|---|
| Date | 2015-07-08 17:20 -0500 |
| Message-ID | <mnk7j8$5dv$2@dont-email.me> |
| In reply to | #64915 |
James Kuyper wrote:
> On 07/08/2015 09:12 AM, Les Cargill wrote:
>> James Kuyper wrote:
>>> On 07/07/2015 10:52 PM, Les Cargill wrote:
> ...
>>>> char *s = something();
>>>>
>>>> printf(":%s: 0x%08x\n",s,(int)s);
>>>>
>>>> Every. Single. Attempt. To improve on this. Fails. Repeatedly.
>>>
>>> Personally, I'd use %p and (void*)s, but I presume that you have your
>>> reasons for avoiding it.
>>>
>>
>> Not really. I recall vaguely something unsettling with %p, but
>> *for now* it's not that unusual to be able to cast a pointer thru an int.
>
> Well, the reason I presumed "you have your reasons" is that I can think
> of a few myself. First of all, the standard does not specify the format
> of the output from %p. Therefore, it could be hexadecimal, decimal, base
> 36, octal, or even binary. It might have "decorations" such as in
> FFEF:0123 to indicate segment:offset. It needn't even have any part that
> looks like a number, though I have a hard time imagining why anyone
> would choose a format that didn't have number-like parts.
> The single biggest issue: there's no upper limit on the length of the
> output - for example, in principle it could be a decimal number written
> out in English: "One billion two hundred and thirty four million five
> hundred and sixty seven thousand eight hundred and ninety".
>
:)
The cast to int ( or not even that ) and use of 0x%08x is an old trope
from debug prints from the long ago times, and simply
what I'd typed in.
%p is actually preferred, I'd think.
--
Les Cargill
[toc] | [prev] | [next] | [standalone]
| From | Phil Carmody <pc+usenet@asdf.org> |
|---|---|
| Date | 2015-07-09 11:08 +0300 |
| Message-ID | <87egkhda8k.fsf@bazspaz.fatphil.org> |
| In reply to | #64890 |
Les Cargill <lcargill99@comcast.com> writes:
> Bartc wrote:
> > On 06/07/2015 17:04, Rick C. Hodgin wrote:
> >> In 2015, what suggestions would you have for changing anything about
> >> the format specifiers used in the printf functions? Leave them as
> >> they are? Or change this or that about them?
> >
> > In 2015, the whole notion of having to tell a compiler what it already
> > knows - the type of the values it's printing - is outdated.
>
> No, it is not.
>
> Example 1:
>
> char *s = something();
>
> printf(":%s: 0x%08x\n",s,(int)s);
>
> Every. Single. Attempt. To improve on this. Fails. Repeatedly.
Well, apart from:
printf(":%s: %#08x\n", s, (unsigned int)s);
perhaps.
But yes, your point is made. It's nice to see so many jump to
printf's defence! In. Such. Absolute. Terms.
Phil
--
A well regulated militia, being necessary to the security of a free state,
the right of the people to keep and bear arms, shall be well regulated.
[toc] | [prev] | [next] | [standalone]
| From | Phil Carmody <pc+usenet@asdf.org> |
|---|---|
| Date | 2015-07-08 20:30 +0300 |
| Message-ID | <87mvz6d0an.fsf@bazspaz.fatphil.org> |
| In reply to | #64778 |
Bartc <bc@freeuk.com> writes: > On 06/07/2015 17:04, Rick C. Hodgin wrote: > > In 2015, what suggestions would you have for changing anything about > > the format specifiers used in the printf functions? Leave them as > > they are? Or change this or that about them? > > In 2015, the whole notion of having to tell a compiler what it already > knows - the type of the values it's printing - is outdated. You're confusing the compiler and the runtime. The compiler knows the types at compile time, but it does not tell the runtime that information. So it has to come from somewhere else, namely encoded in one or more parameters. One thing that makes me laugh is that despite apparently everyone's superficial hate of it, it gets inherited into so many other languages. I don't believe anyone's hate of the *f functions can match my hate of C++'s '>>' and '<<'. There, I said it. Phil -- A well regulated militia, being necessary to the security of a free state, the right of the people to keep and bear arms, shall be well regulated.
[toc] | [prev] | [next] | [standalone]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-07-08 18:56 +0100 |
| Message-ID | <mnjo60$vt7$1@dont-email.me> |
| In reply to | #64939 |
On 08/07/2015 18:30, Phil Carmody wrote: > Bartc <bc@freeuk.com> writes: >> On 06/07/2015 17:04, Rick C. Hodgin wrote: >>> In 2015, what suggestions would you have for changing anything about >>> the format specifiers used in the printf functions? Leave them as >>> they are? Or change this or that about them? >> >> In 2015, the whole notion of having to tell a compiler what it already >> knows - the type of the values it's printing - is outdated. > > You're confusing the compiler and the runtime. The compiler > knows the types at compile time, but it does not tell the > runtime that information. So it has to come from somewhere > else, namely encoded in one or more parameters. Exactly. And it is that that is outdated. The compiler can easily tell the runtime what the types are in many cases, so why not? That will also make maintenance a bit simpler. > One thing that makes me laugh is that despite apparently everyone's > superficial hate of it, it gets inherited into so many other languages. Yes; normally I use my own languages but still have to call printf and sprintf from time to time. Often, though, in order to /implement/ something more advanced. -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | gordonb.lmwiv@burditt.org (Gordon Burditt) |
|---|---|
| Date | 2015-07-09 11:09 -0500 |
| Message-ID | <4o2dnboKHbU6AQPInZ2dnUU7-L2dnZ2d@posted.internetamerica> |
| In reply to | #64948 |
> Exactly. And it is that that is outdated. The compiler can easily tell
> the runtime what the types are in many cases, so why not? That will also
> make maintenance a bit simpler.
Let's suppose you wanted to design a new version of varargs that
would tell you the types of the arguments passed, with all the
detail that the compiler has, so you could check them. The key
(and problem) to this is the type_t type, which represents everything
known about a C type. The internal representation of a type_t is
implementation-defined and probably requires a lot of thought
to keep it from hogging all memory.
There's a new varargs interface, with some magic
keyword to use to declare that a function uses it, which
causes the compiler to implicity pass extra information.
It passes:
pass the fixed arguments, as usual;
for each varargs argument {
Pass a type_t for the type of the varargs argument;
Pass the argument;
}
pass a (type_t) NULL argument, which acts as an EOF for the
argument list, so you can tell how many arguments
were passed.
One of the big problems with this idea is the number of bits
required to represent a type_t. A "simple" function pointer
to a function with 100 arguments, each of which has a 6-dimensional
array needs storage that must include 600 array bounds, and if
they are represented at a fixed size, need to be the maximum size.
So, maybe a 4.8k type_t for an 8-byte function pointer on a 64-bit
machine?
type_t comes with a whole bunch of functions to do "type calculation"
on a type to come up with more types.
You can compare two type_t's. If the types aren't the same (down
to signed/unsigned, array dimensions, int vs. long even if both
are the same size, const, volatile, function pointer arguments, etc.)
then they should not compare equal.
type_t _type_of(x) returns a type_t for the type of x, if x is a
variable, or for the given type, if it's a type (or typedef).
bool _type_is_integer(type_t x)
bool _type_is_floating(type_t x)
(also need to deal with complex, and enum)
bool _type_is_data_pointer(type_t x)
bool _type_is_struct(type_t x)
bool _type_is_union(type_t x)
bool _type_is_array(type_t x)
bool _type_is_function_pointer(type_t x)
These functions return 1 or 0 if the outermost type falls in
the category indicated.
type_t _type_deref(type_t x)
This function returns the type that results from dereferencing
the given type (better check _type_is_data_pointer(x) first).
For example, _type_deref(_type_of(char *)) == _type_of(char)
(A pointer is a pointer. You need to call _type_deref(x)
to figure out what it points at.)
type_t _type_ref(type_t x)
This function returns the type that results from taking the
address of the given type.
int _type_struct_member_count(type_t x)
This function returns the number of members in a struct type.
type_t _type_struct_member(type_t x, size_t n)
This function returns the type of the nth member of a struct,
given a struct type.
int _type_function_pointer_arg_count(type_t x)
This function returns the number of arguments needed to call
via a function pointer.
type_t _type_function_pointer_arg(type_t x, int n)
This function returns the type of the nth argument of a
function pointer, given a function pointer type.
type_t _type_array_elements(type_t x)
This function returns the dimension of the array (in elements)
size_t _type_sizeof(type_t x)
This type returns the size of the type
type_t _type_usualarithmeticconversions(type_t x1, type_t x2)
This function returns the type of the result of an arithmetic
operation between two types x1 and x2.
type_t _type_varargsargumentpromotion(type_t x)
This function returns the type of x1 as it is passed as a
varargs argument (char promoted to int, etc.)
type_t _type_is_assignment_compatible(type_t x1, type_t x2)
This function returns 1 if assigning type x2 to type x1
is assignment-compatible.
Some of the numeric return types are a little iffy. Is the number
of structure members or function arguments really limited to INT_MAX?
If there are really no limits to this, as your favorite version of
GCC tries to do, then you've got a problem, as sizeof(type_t) is
infinite.
And there's probably hundreds of needed functions I have left out.
An additional problem arises that once you've figured out you have
an integer type, you want to check if it's the *right* one, say,
with _type_integer_base_type(type_t x). You can check signed and
unsigned versions of char, short, int, long, long long, and intmax_t,
but int19_t may exist on some platforms but doesn't on many/most,
and there's no list of what to check.
A smarter version of sscanf() could at least check that
type_is_data_pointer(x) is true, and _type_sizeof(_type_deref(x))
is equal to the size of whatever type is implied by the format
conversion. And you could check that the signedness matches, which
will probably cause problems with existing code that likes to print
signed integers in hex. You could also insist that a particular
format conversion goes with int only, not long (even if they are
the same size).
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@hotmail.com> |
|---|---|
| Date | 2015-07-09 14:05 -0500 |
| Message-ID | <mnmgsu$5jl$1@news.albasani.net> |
| In reply to | #65020 |
On 7/9/2015 11:09 AM, Gordon Burditt wrote: >> Exactly. And it is that that is outdated. The compiler can easily tell >> the runtime what the types are in many cases, so why not? That will also >> make maintenance a bit simpler. > > Let's suppose you wanted to design a new version of varargs that > would tell you the types of the arguments passed, with all the > detail that the compiler has, so you could check them. The key > (and problem) to this is the type_t type, which represents everything > known about a C type. The internal representation of a type_t is > implementation-defined and probably requires a lot of thought > to keep it from hogging all memory. > <big snip> a general "sane" solution is to make it be an opaque integer type. and basic types will map done to "sane" integer values. cheapest for dispatch would be to use 16-bit values, which are (probably) sufficient for most current applications, and are a lot more switch-friendly than 32-bit values. probably, in a spec, it would make sense to leave it undefined what size integer it is, or exactly how the bits are laid out or what information is encoded directly. at least at present, IME, it seems uncommon to exceed a few thousand unique types. even with fairly big libraries and headers (such as throwing "windows.h" and similar in the mix). but, for worst-case, could make sense to allow for a larger type-space if-needed. if we assume that only a small number of these will ever by type-checked (others will not be assigned ID values), then it should fit nicely within a 16-bit space. you can determine whether or not two types are equal via the '==' or '!=' operators, provided that the same types will reliably give the same values. more complex type information would likely depend on compiler, linker, and runtime support, and the use of reflection metadata, and effective handling would thus be more complex and expensive. a subset is to only require that the types have unique ID values between compilation units, but leave it undefined if it is possible to know anything more about the types (say, whether or not any sort of reflection is possible). an implementation may fail to provide any sort of reflection about the types, or possibly this is a special feature which would need to be enabled at compile time. granted, getting unique IDs which are consistent between compilation units would likely require dedicated linker support, and between libraries would almost invariably require runtime support and some basic level of metadata (need not be reflection data, but possibly 128-bit hashes and relying on there being a statistically low chance of an accidental collision). IOW: if type A and type B have the same 128-bit hash value, they are assumed to be equivalent. even if we have many thousands of types, we are still looking at kB when with the use of 128-bit hashes, and the likelihood of two libraries both checking different types (out of sets of a few thousand) which produce identical 128-bit hashes, is statistically very low. granted, an easier solution would be leaving it undefined for non-primitive types if the source and destination are not in the same DLL or SO. ex: "unsigned char" or "int *" would be ensured to always have a consistent type ID. "struct foo_s *", however, is mostly at the mercy of the implementation, and at most maybe it will tell you whether or not it is a pointer, but may not be required to be able to tell you what "foo_s" contains, or if "foo_s" as seen from two different libraries are, in fact, the same "foo_s". but, it isn't *that* hard to make two different "foo_s" structs comparable, we may just hash their names and contents. likewise, a function signature can be similarly hashed, ...
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-07-08 11:27 -0700 |
| Message-ID | <lnd202a4iq.fsf@kst-u.example.com> |
| In reply to | #64939 |
Phil Carmody <pc+usenet@asdf.org> writes:
> Bartc <bc@freeuk.com> writes:
>> On 06/07/2015 17:04, Rick C. Hodgin wrote:
>> > In 2015, what suggestions would you have for changing anything about
>> > the format specifiers used in the printf functions? Leave them as
>> > they are? Or change this or that about them?
>>
>> In 2015, the whole notion of having to tell a compiler what it already
>> knows - the type of the values it's printing - is outdated.
>
> You're confusing the compiler and the runtime. The compiler
> knows the types at compile time, but it does not tell the
> runtime that information. So it has to come from somewhere
> else, namely encoded in one or more parameters.
>
> One thing that makes me laugh is that despite apparently everyone's
> superficial hate of it, it gets inherited into so many other languages.
>
> I don't believe anyone's hate of the *f functions can match my
> hate of C++'s '>>' and '<<'. There, I said it.
It would be interesting to have a C extension (perhaps becoming a
standard feature in a future version) that provides a new form of
variadic function.
This is off the top of my head, and doubtless has numerous flaws.
Existing variadic functions would remain as they are, for backward
compatibility.
A new syntax such as
int func(int arg1, ... other_args);
where "other_args" can be any arbitrary identifier, would permit calls
just like existing calls to variadic functions. In this case, a call
must provide at least one argument, and the first argument must be of
type int (or implicitly convertible to int). The remaining arguments,
if any, can be of any type. Unlike for varaidic functions, no fixed
arguments would be required.
Inside the function, other_args would be of some new type, say
"arg_list" defined in a new header. It would encode, somehow, the
number and types of the remaining arguments. The compiler would be
responsible for generating code that passes an argument of the correct
type. Perhaps this would be limited to certain types (say, predefined
numeric types and pointers to them).
The function might still use the <stdarg.h> macros to retrieve the
argument values, but it would *know* the actual types passed by the
caller.
A simplified version of printf might be:
int print(... args);
so that this:
int n = 42;
print("n = ", n, ", &n = ", &n, "\n");
would behave like:
printf("n = %d, &n = %p\n", n, (void*)&n);
The implementation of print() would be moderately complicated (it would
have to interpert the type information in the "args" parameter and use
something like a switch statement to print the values), but that
wouldn't matter when you're calling it. Unlike with printf(), there
would be no opportunity to use a format string that's incompatible with
the actual arguments.
(Character literals are of type int, so that could be a source of bugs,
but using "\n" rather than '\n' avoid that problem.)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@hotmail.com> |
|---|---|
| Date | 2015-07-08 15:07 -0500 |
| Message-ID | <mnk05s$f7d$1@news.albasani.net> |
| In reply to | #64953 |
On 7/8/2015 1:27 PM, Keith Thompson wrote:
> Phil Carmody <pc+usenet@asdf.org> writes:
>> Bartc <bc@freeuk.com> writes:
>>> On 06/07/2015 17:04, Rick C. Hodgin wrote:
>>>> In 2015, what suggestions would you have for changing anything about
>>>> the format specifiers used in the printf functions? Leave them as
>>>> they are? Or change this or that about them?
>>>
>>> In 2015, the whole notion of having to tell a compiler what it already
>>> knows - the type of the values it's printing - is outdated.
>>
>> You're confusing the compiler and the runtime. The compiler
>> knows the types at compile time, but it does not tell the
>> runtime that information. So it has to come from somewhere
>> else, namely encoded in one or more parameters.
>>
>> One thing that makes me laugh is that despite apparently everyone's
>> superficial hate of it, it gets inherited into so many other languages.
>>
>> I don't believe anyone's hate of the *f functions can match my
>> hate of C++'s '>>' and '<<'. There, I said it.
>
> It would be interesting to have a C extension (perhaps becoming a
> standard feature in a future version) that provides a new form of
> variadic function.
>
> This is off the top of my head, and doubtless has numerous flaws.
>
> Existing variadic functions would remain as they are, for backward
> compatibility.
>
> A new syntax such as
>
> int func(int arg1, ... other_args);
>
> where "other_args" can be any arbitrary identifier, would permit calls
> just like existing calls to variadic functions. In this case, a call
> must provide at least one argument, and the first argument must be of
> type int (or implicitly convertible to int). The remaining arguments,
> if any, can be of any type. Unlike for varaidic functions, no fixed
> arguments would be required.
>
> Inside the function, other_args would be of some new type, say
> "arg_list" defined in a new header. It would encode, somehow, the
> number and types of the remaining arguments. The compiler would be
> responsible for generating code that passes an argument of the correct
> type. Perhaps this would be limited to certain types (say, predefined
> numeric types and pointers to them).
>
<snip>
yes, I have actually considered something very similar for C-Aux, though
it is a "yet to be done" feature.
in the VM, when calls are decoded, the VM keeps track of which arguments
are which type as part of a "CallInfo" structure.
as part of the call (or on the callee end), this could be made available
as an "ArgsInfo" structure or similar, with pointers for the argument
list, argument types, and an argument count.
currently in the VM, it doesn't store full type-info, but merely a byte
indicating the "basic type" for the argument.
for a native ABI, likely this would need to be handled on the caller
end, either by tweaking the ABI in this case (passing a structure rather
than arguments-as-usual), or by storing side-info (such as by passing a
pointer in a register to a structure with info about the argument list).
storing predefined type IDs and pointers makes more sense, as otherwise
it becomes a fair bit more complex and expensive to store fully
fleshed-out type information. say, if you indicate that a type is a
structure, you would then need to indicate what type it is, how it is
laid out, ...
so, it is simpler mostly just to encode primitive types (as 8 or 16 bits
each), and leave things like structures as opaque types or as ABI specific.
possible (16-bit range):
0- 255: reserved for primitive types
256- 2047: pointers to primitive types (* to *******).
2048- 4095: implementation reserved fixed-types
4096-32767: reserved
32768-65535: complex types (decoding depends on external metadata).
say, for example (in SysV/AMD64):
RDI, RSI, RDX, RCX, R8, R9, ... same as usual.
either:
RAX: XMM arg count (as before)
R11: ArgsInfo
or:
RAX: ArgsInfo (replaces XMM arg count)
possible C-side interface:
va2_list lst; //new args list type
va2_copy(dst, src) //copy list
va2_arg(lst, type) //get next arg
va2_argisp(lst, type) //check if next arg is type
va2_get(lst, idx, type) //get arg by index
va2_getisp(lst, idx, type) //checks if index'ed arg is type
possibly, explicit type IDs could be supported:
va2_argty(lst) //type ID for next argument
va2_getty(lst, idx) //type ID for argument by index
va2_typeid(type) //get type-ID for a given type
these could be required to expand to constant integer values, say, so
that it is possible to use a switch:
switch(va2_argty(lst))
{
case va2_typeid(int): ... break;
case va2_typeid(long long): ... break;
case va2_typeid(float): ... break;
...
}
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@hotmail.com> |
|---|---|
| Date | 2015-07-06 23:39 -0500 |
| Message-ID | <mnflej$8ou$1@news.albasani.net> |
| In reply to | #64771 |
On 7/6/2015 11:04 AM, Rick C. Hodgin wrote: > In 2015, what suggestions would you have for changing anything about > the format specifiers used in the printf functions? Leave them as > they are? Or change this or that about them? > despite their limitations, the C printf formatting system is actually one of the more useable ones. possible additions: ability to (optionally) specify argument numbers, rather than arguments always being processed in-order; user-extensible format types(*1); more "good" options for things like formatting float numbers (*2); ... *1: maybe hooks could be registered to allow plugging print-handling of custom or specialized datatypes. *2: possible examples: left-justified numbers padded to the right with spaces; space-padded center-aligned numbers on both the left and right; ability for numbers to have a variable number of digits following the decimal point; ... though, on a related topic, also functions could be nice to help make things like parsing data from strings easier, such as functions to help match and read tokens, split strings into tokens, numeric conversion functions that can handle a wider range of inputs, ... though, yes, pretty much all of this are things that are generally done by supplying ones own code.
[toc] | [prev] | [next] | [standalone]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-07-07 10:19 +0100 |
| Message-ID | <mng5gr$hdm$1@dont-email.me> |
| In reply to | #64830 |
On 07/07/2015 05:39, BGB wrote:
> On 7/6/2015 11:04 AM, Rick C. Hodgin wrote:
>> In 2015, what suggestions would you have for changing anything about
>> the format specifiers used in the printf functions? Leave them as
>> they are? Or change this or that about them?
>>
>
> despite their limitations, the C printf formatting system is actually
> one of the more useable ones.
They work fine except they are too closely tied to the types of the
arguments:
(1) You have to know the exact type of each argument (and the type might
depend on some imported name whose declaration is buried in a header)
(2) Every time you change the type of a variable somewhere, now you
might have to change a hundred print formats. And change them back again
when you change your mind!
> possible additions:
> ability to (optionally) specify argument numbers, rather than arguments
> always being processed in-order;
I think that already exists. Something like printf("%$2d %$1d",a,b) to
print b first then a.
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@hotmail.com> |
|---|---|
| Date | 2015-07-07 07:57 -0500 |
| Message-ID | <mngik5$t97$1@news.albasani.net> |
| In reply to | #64840 |
On 7/7/2015 4:19 AM, Bartc wrote:
> On 07/07/2015 05:39, BGB wrote:
>> On 7/6/2015 11:04 AM, Rick C. Hodgin wrote:
>>> In 2015, what suggestions would you have for changing anything about
>>> the format specifiers used in the printf functions? Leave them as
>>> they are? Or change this or that about them?
>>>
>>
>> despite their limitations, the C printf formatting system is actually
>> one of the more useable ones.
>
> They work fine except they are too closely tied to the types of the
> arguments:
>
> (1) You have to know the exact type of each argument (and the type might
> depend on some imported name whose declaration is buried in a header)
>
> (2) Every time you change the type of a variable somewhere, now you
> might have to change a hundred print formats. And change them back again
> when you change your mind!
>
these are not usually a big issue IME. if the type is unstable enough
that this becomes an issue, isn't something like a "Whatever_ToString()"
style function better?...
alternatively, you could cast to a known type, and use that type.
>
>> possible additions:
>> ability to (optionally) specify argument numbers, rather than arguments
>> always being processed in-order;
>
> I think that already exists. Something like printf("%$2d %$1d",a,b) to
> print b first then a.
>
I am not aware of such a syntax, and don't see it listed anywhere.
[toc] | [prev] | [next] | [standalone]
| From | Bartc <bc@freeuk.com> |
|---|---|
| Date | 2015-07-07 14:15 +0100 |
| Message-ID | <mngjas$1s7$1@dont-email.me> |
| In reply to | #64849 |
On 07/07/2015 13:57, BGB wrote:
> On 7/7/2015 4:19 AM, Bartc wrote:
>> (1) You have to know the exact type of each argument (and the type might
>> (2) Every time you change the type of a variable somewhere, now you
>> might have to change a hundred print formats.
> these are not usually a big issue IME. if the type is unstable enough
> that this becomes an issue, isn't something like a "Whatever_ToString()"
> style function better?...
>
> alternatively, you could cast to a known type, and use that type.
An expression might start as a normal type such as int, for which %d is
used, and you wouldn't bother with cast, but then it becomes something
weird (uintxx_t for example), or buried under typedefs. Then having to
inserts casts as as much work as changing the formats. And the casts
won't cover the case where an expression type becomes wider, or switches
between int and float.
There are all these ways around it, but it shouldn't be necessary,
unless there is a massive change in the type (from int to a struct for
example) which will need the format changed anyway.
>> I think that already exists. Something like printf("%$2d %$1d",a,b) to
>> print b first then a.
>>
>
> I am not aware of such a syntax, and don't see it listed anywhere.
Google for 'printf positional arguments'. It might be a POSIX extension.
But you might be out of luck if you're using MSVC.
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-07-07 14:46 +0100 |
| Message-ID | <87zj383wti.fsf@bsb.me.uk> |
| In reply to | #64850 |
Bartc <bc@freeuk.com> writes:
> On 07/07/2015 13:57, BGB wrote:
>> On 7/7/2015 4:19 AM, Bartc wrote:
On positional printing:
<snip>
>>> I think that already exists. Something like printf("%$2d %$1d",a,b) to
>>> print b first then a.
It's "%2$d %1$d" in the versions I know of. This order (the argument
number coming first) allows for a width and/or precision to follow.
>> I am not aware of such a syntax, and don't see it listed anywhere.
>
> Google for 'printf positional arguments'. It might be a POSIX
> extension.
It is. In the POSIX version, even the positional argument from which to
take a variable width or precision can be specified:
printf("%2$*1.*3$f\n", width, my_number, prec);
The result is a bit hairy!
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | BGB <cr88192@hotmail.com> |
|---|---|
| Date | 2015-07-07 09:37 -0500 |
| Message-ID | <mngofd$p4q$1@news.albasani.net> |
| In reply to | #64850 |
On 7/7/2015 8:15 AM, Bartc wrote:
> On 07/07/2015 13:57, BGB wrote:
>> On 7/7/2015 4:19 AM, Bartc wrote:
>
>>> (1) You have to know the exact type of each argument (and the type might
>
>>> (2) Every time you change the type of a variable somewhere, now you
>>> might have to change a hundred print formats.
>
>> these are not usually a big issue IME. if the type is unstable enough
>> that this becomes an issue, isn't something like a "Whatever_ToString()"
>> style function better?...
>>
>> alternatively, you could cast to a known type, and use that type.
>
> An expression might start as a normal type such as int, for which %d is
> used, and you wouldn't bother with cast, but then it becomes something
> weird (uintxx_t for example), or buried under typedefs. Then having to
> inserts casts as as much work as changing the formats. And the casts
> won't cover the case where an expression type becomes wider, or switches
> between int and float.
>
I have just not really had issues with this one personally.
then again, I have also usually used explicit casts for cases where
there was any uncertainty.
though, granted, have not generally used 'intxx_t' or 'uintxx_t' style
types, as generally the existence of 'stdint.h' has been a bit hit or
miss sometimes.
then again, I also remember the times where 'long long' couldn't really
be safely used, as only some compilers supported it, but it is pretty
much supported everywhere now (vs in the past where semi-portable 64-bit
integer types required a bit more contortions, more like the present
situation with using 128 bit integers...).
though, luckily I got into things recently enough that I didn't need to
deal with past issues, for example, compilers only accepting:
whatever(x, y) int x, y; { ... }
this was mostly dead by the late-90s / early 2000s (most I had dealt
with it was trying to get stuff compiled for an older M68K-based Mac).
this was such a useful experience, the thing couldn't even run
Wolfenstein3D (but could run SimCity at least...).
it was a bit unimpressive at the time vs PCs which could run things like
Quake II and Quake 3 Arena and similar...
> There are all these ways around it, but it shouldn't be necessary,
> unless there is a massive change in the type (from int to a struct for
> example) which will need the format changed anyway.
>
this is where the existence of customizable specifiers could be useful,
as opposed to needing to resort to manually using functions to convert
things to temporary strings.
or using their own customized string printing and formatting functions,
where the program supplies its own custom 'sprintf'/'vsprintf' style
interface, which is used for most of the internal printing/logging
functions, and provides more consistent printing behavior across
different underlying C runtime libraries.
>>> I think that already exists. Something like printf("%$2d %$1d",a,b) to
>>> print b first then a.
>>>
>>
>> I am not aware of such a syntax, and don't see it listed anywhere.
>
> Google for 'printf positional arguments'. It might be a POSIX extension.
>
> But you might be out of luck if you're using MSVC.
>
apparently, it involves using "_sprintf_p()" and similar, rather than
being supported by the normal printf/sprintf/...
[toc] | [prev] | [next] | [standalone]
| From | Phil Carmody <pc+usenet@asdf.org> |
|---|---|
| Date | 2015-07-09 11:24 +0300 |
| Message-ID | <87615td9hr.fsf@bazspaz.fatphil.org> |
| In reply to | #64849 |
BGB <cr88192@hotmail.com> writes:
> On 7/7/2015 4:19 AM, Bartc wrote:
> > On 07/07/2015 05:39, BGB wrote:
> >> possible additions:
> >> ability to (optionally) specify argument numbers, rather than arguments
> >> always being processed in-order;
> >
> > I think that already exists. Something like printf("%$2d %$1d",a,b) to
> > print b first then a.
>
> I am not aware of such a syntax, and don't see it listed anywhere.
GCC supports it as an extension. Which implies that it's actually
glibc that supports it as an extension, and therefore that it should
be available to any compiler linking to glibc for *printf, diagnostics
permitting.
$ man 3 printf
...
argument. The C99 standard does not include the style using '$', which
comes from the Single Unix Specification. If the style using '$' is
...
I'd like to see that bubbled into ISO C, to be honest, I find it
extremely useful.
Phil
--
A well regulated militia, being necessary to the security of a free state,
the right of the people to keep and bear arms, shall be well regulated.
[toc] | [prev] | [next] | [standalone]
Page 3 of 5 — ← Prev page 1 2 [3] 4 5 Next page →
Back to top | Article view | comp.lang.c
csiph-web