Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #169256 > unrolled thread

FAQ list update: Q1.1: choosing types

Started byscs@eskimo.com (Steve Summit)
First post2023-02-13 15:18 +0000
Last post2023-02-15 05:31 -0800
Articles 20 on this page of 25 — 14 participants

Back to article view | Back to comp.lang.c


Contents

  FAQ list update: Q1.1: choosing types scs@eskimo.com (Steve Summit) - 2023-02-13 15:18 +0000
    Re: FAQ list update: Q1.1: choosing types Anton Shepelev <anton.txt@g{oogle}mail.com> - 2023-02-13 18:27 +0300
    Re: FAQ list update: Q1.1: choosing types scott@slp53.sl.home (Scott Lurndal) - 2023-02-13 16:27 +0000
      Re: FAQ list update: Q1.1: choosing types Oğuz <oguzismailuysal@gmail.com> - 2023-02-14 08:55 +0300
    Re: FAQ list update: Q1.1: choosing types Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2023-02-13 18:07 +0000
    Re: FAQ list update: Q1.1: choosing types Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-02-13 10:48 -0800
    Re: FAQ list update: Q1.1: choosing types Kaz Kylheku <864-117-4973@kylheku.com> - 2023-02-14 03:10 +0000
      Re: FAQ list update: Q1.1: choosing types Blue-Maned_Hawk <bluemanedhawk@gmail.com> - 2023-02-14 17:33 -0500
    Re: FAQ list update: Q1.1: choosing types Öö Tiib <ootiib@hot.ee> - 2023-02-13 23:24 -0800
    Re: FAQ list update: Q1.1: choosing types bart c <bart4858@gmail.com> - 2023-02-14 06:22 -0800
      Re: FAQ list update: Q1.1: choosing types Blue-Maned_Hawk <bluemanedhawk@gmail.com> - 2023-02-14 17:48 -0500
    Re: FAQ list update: Q1.1: choosing types John Dill <jadill33@gmail.com> - 2023-02-14 08:17 -0800
      Re: FAQ list update: Q1.1: choosing types Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-02-14 12:34 -0800
        Re: FAQ list update: Q1.1: choosing types John Dill <jadill33@gmail.com> - 2023-02-15 10:04 -0800
          Re: FAQ list update: Q1.1: choosing types Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-02-15 10:28 -0800
            Re: FAQ list update: Q1.1: choosing types Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-02-15 10:57 -0800
              Re: FAQ list update: Q1.1: choosing types Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-02-15 11:17 -0800
                Re: FAQ list update: Q1.1: choosing types Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-02-15 11:32 -0800
            Re: FAQ list update: Q1.1: choosing types John Dill <jadill33@gmail.com> - 2023-02-15 11:01 -0800
              Re: FAQ list update: Q1.1: choosing types Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-02-15 11:28 -0800
                Re: FAQ list update: Q1.1: choosing types John Dill <jadill33@gmail.com> - 2023-02-15 14:00 -0800
    Re: FAQ list update: Q1.1: choosing types Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-02-15 02:54 -0800
    Re: FAQ list update: Q1.1: choosing types Anton Shepelev <anton.txt@g{oogle}mail.com> - 2023-02-15 14:43 +0300
    Re: FAQ list update: Q1.1: choosing types David Brown <david.brown@hesbynett.no> - 2023-02-15 13:55 +0100
      Re: FAQ list update: Q1.1: choosing types Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-02-15 05:31 -0800

Page 1 of 2  [1] 2  Next page →


#169256 — FAQ list update: Q1.1: choosing types

Fromscs@eskimo.com (Steve Summit)
Date2023-02-13 15:18 +0000
SubjectFAQ list update: Q1.1: choosing types
Message-ID<2023Feb13.1015.scs.0001@quinine2.local>
In its very first question, the FAQ list currently says:

	If you might need large values (above 32,767 or
	below -32,767), use long.  Otherwise, if space is
	very important (i.e. if there are large arrays or
	many structures), use short.  Otherwise, use int.
	If well-defined overflow characteristics are important
	and negative values are not, or if you want to steer
	clear of sign-extension problems when manipulating bits
	or bytes, use one of the corresponding unsigned types.
	(Beware when mixing signed and unsigned values in
	expressions, though; see question 3.19.)

	Although character types (especially unsigned char) can
	be used as ``tiny'' integers, doing so is sometimes more
	trouble than it's worth.  The compiler will have to emit
	extra code to convert between char and int (making the
	executable larger), and unexpected sign extension can be
	troublesome.  (Using unsigned char can help; see question
	12.1 for a related problem.)

	A similar space/time tradeoff applies when deciding
	between float and double.  (Many compilers still convert
	all float values to double during expression evaluation.)

	...If for some reason you need to declare something with
	an exact size (usually the only good reason for doing so
	is when attempting to conform to some externally-imposed
	storage layout, but see question 20.5), be sure to
	encapsulate the choice behind an appropriate typedef,
	but see question 1.3.

Besides cleaning up the wording (this answer, like much of my
writing, is afflicted with Too Many Parentheticals :-) ), I am
strongly considering making one or two additional, potentially
controversial points:

	If you want to make the considered assumption that your
	code will only ever run on "modern" hardware, you can say
	that plain int can hold up to +-2147483647 (that is, has
	32 bits).

	Some coding guidelines, notably MISRA, deprecate the
	"abstract" types short, int, and long, and mandate always
	using exact-size types like int16_t and int32_t.

To the first point, believe me, I do know what the Standard
guarantees about type int, and I remember well the pejorative
phrase "All the world's a VAX" as promulgated in, among other
things, Henry Spencer's 10 Commandments.  But I also know that
the codebase I work on every day in my day job makes this
assumption, and I'm pretty sure I'm not alone.

To the second point, while I personally disagree up, down, and
sideways with the dictum "don't use plain int", I can't ignore the
fact that many practicing C programmers do advocate and follow it,
and many projects faithfully honor MISRA.

Opinions (in support or denigration of either point) welcome.

					Steve Summit
					scs@eskimo.com

[toc] | [next] | [standalone]


#169257

FromAnton Shepelev <anton.txt@g{oogle}mail.com>
Date2023-02-13 18:27 +0300
Message-ID<20230213182737.cf2e68f94204d62270fbe304@g{oogle}mail.com>
In reply to#169256
Steve Summit:

> To the first point, believe me, I do know what the
> Standard guarantees about type int, and I remember well
> the pejorative phrase "All the world's a VAX" as
> promulgated in, among other things, Henry Spencer's 10
> Commandments.  But I also know that the codebase I work on
> every day in my day job makes this assumption, and I'm
> pretty sure I'm not alone.
> [...]
> Opinions (in support or denigration of either point)
> welcome.

I have a philosophical consideration with pracitcal
implications: the closer you adhere to the ideal standard C,
the more future-proof and maintainance-free the FAQ becomes.
That said, one apprach would be to write about the standard
C in vacuum, without regard to (currently) modern compilers,
practices, and assumptions, which fall under the volatile
subject of "Practical C" rather than the more stable and
fundamental "C in itself."

-- 
()  ascii ribbon campaign -- against html e-mail
/\  www.asciiribbon.org   -- against proprietary attachments

[toc] | [prev] | [next] | [standalone]


#169259

Fromscott@slp53.sl.home (Scott Lurndal)
Date2023-02-13 16:27 +0000
Message-ID<uxtGL.613679$8_id.534973@fx09.iad>
In reply to#169256
scs@eskimo.com (Steve Summit) writes:
>In its very first question, the FAQ list currently says:
>
>	If you might need large values (above 32,767 or
>	below -32,767), use long.  Otherwise, if space is
>	very important (i.e. if there are large arrays or
>	many structures), use short.  Otherwise, use int.
>	If well-defined overflow characteristics are important
>	and negative values are not, or if you want to steer
>	clear of sign-extension problems when manipulating bits
>	or bytes, use one of the corresponding unsigned types.
>	(Beware when mixing signed and unsigned values in
>	expressions, though; see question 3.19.)
>
>	Although character types (especially unsigned char) can
>	be used as ``tiny'' integers, doing so is sometimes more
>	trouble than it's worth.  The compiler will have to emit
>	extra code to convert between char and int (making the
>	executable larger), and unexpected sign extension can be
>	troublesome.  (Using unsigned char can help; see question
>	12.1 for a related problem.)
>
>	A similar space/time tradeoff applies when deciding
>	between float and double.  (Many compilers still convert
>	all float values to double during expression evaluation.)
>
>	...If for some reason you need to declare something with
>	an exact size (usually the only good reason for doing so
>	is when attempting to conform to some externally-imposed
>	storage layout, but see question 20.5), be sure to
>	encapsulate the choice behind an appropriate typedef,
>	but see question 1.3.
>
>Besides cleaning up the wording (this answer, like much of my
>writing, is afflicted with Too Many Parentheticals :-) ), I am

That description is way out of date.   The idea that extending
from a byte to a word causes the executable to be larger is
misleading at best, particularly given that byte-width loads
will extend (sign or zero) the value to the target register
in most cases automatically with no additional code required.

[toc] | [prev] | [next] | [standalone]


#169265

FromOğuz <oguzismailuysal@gmail.com>
Date2023-02-14 08:55 +0300
Message-ID<tsf7oh$2e9n2$1@dont-email.me>
In reply to#169259
On 2/13/23 7:27 PM, Scott Lurndal wrote:
> byte-width loads
> will extend (sign or zero) the value to the target register
> in most cases automatically with no additional code required.

Can you provide an example where this happens?
One of my toy programs spend too much time on a `movsbl' instruction 
(the C code is `(c & 0xC0) != 0x80', `c' is a char) and I wonder if I 
can eliminate it somehow.

[toc] | [prev] | [next] | [standalone]


#169260

FromLew Pitcher <lew.pitcher@digitalfreehold.ca>
Date2023-02-13 18:07 +0000
Message-ID<tsdu94$272pu$1@dont-email.me>
In reply to#169256
On Mon, 13 Feb 2023 15:18:49 +0000, Steve Summit wrote:

> In its very first question, the FAQ list currently says:
> 
>  If you might need large values (above 32,767 or below -32,767), use
>  long.  Otherwise, if space is very important (i.e. if there are large
>  arrays or many structures), use short.  Otherwise, use int.
>  If well-defined overflow characteristics are important and negative
>  values are not, or if you want to steer clear of sign-extension
>  problems when manipulating bits or bytes, use one of the corresponding
>  unsigned types. (Beware when mixing signed and unsigned values in
>  expressions, though; see question 3.19.)
>
>  Although character types (especially unsigned char) can be used as
>  ``tiny'' integers, doing so is sometimes more trouble than it's worth. 
>  The compiler will have to emit extra code to convert between char and
>  int (making the executable larger), and unexpected sign extension can
>  be troublesome.  (Using unsigned char can help; see question 12.1 for a
>  related problem.)
>
>  A similar space/time tradeoff applies when deciding between float and
>  double.  (Many compilers still convert all float values to double
>  during expression evaluation.)
>
>  ...If for some reason you need to declare something with an exact size
>  (usually the only good reason for doing so is when attempting to
>  conform to some externally-imposed storage layout, but see question
>  20.5), be sure to encapsulate the choice behind an appropriate typedef,
>  but see question 1.3.
> 
> Besides cleaning up the wording (this answer, like much of my writing,
> is afflicted with Too Many Parentheticals :-) ), I am strongly
> considering making one or two additional, potentially controversial
> points:
> 
>  If you want to make the considered assumption that your code will only
>  ever run on "modern" hardware, you can say that plain int can hold up
>  to +-2147483647 (that is, has 32 bits).
> 
>  Some coding guidelines, notably MISRA, deprecate the "abstract" types
>  short, int, and long, and mandate always using exact-size types like
>  int16_t and int32_t.
> 
> To the first point, believe me, I do know what the Standard guarantees
> about type int, and I remember well the pejorative phrase "All the
> world's a VAX" as promulgated in, among other things, Henry Spencer's 10
> Commandments.  But I also know that the codebase I work on every day in
> my day job makes this assumption, and I'm pretty sure I'm not alone.
> 
> To the second point, while I personally disagree up, down, and sideways
> with the dictum "don't use plain int", I can't ignore the fact that many
> practicing C programmers do advocate and follow it,
> and many projects faithfully honor MISRA.
> 
> Opinions (in support or denigration of either point) welcome.

For clarification, the FAQ question in question reads
  "How should I decide which integer type to use?"

Having programmed professionally for 30 years, my answer would differ 
greatly from the FAQ answer as published.

As the "C Language" implementation ecosystem varies in range from 
microcontrollers that can barely muster 65536 bytes of memory and native 
16bit integer math, to systems that support gigabytes (if not terabytes) 
of memory and native 64bit integer math, and a range of compiler-hosted 
low-level optimization tools that range from none to over the top, I'd 
have to say that an answer that concentrates on the machine-level 
implications of "integer type" choices misses the mark.

I would be tempted to answer the question by first saying that the 
programmer should determine the range of values that the code will 
require the integer to hold, then select the closest "integer type" that 
meets (or exceeds) this range. That integer type /might/ be "short" (for 
instance, in a compiler that natively generates 64bit integers), or 
"long" (for instance, in a compiler that natively generates 16bit 
integers), or something else.

/If/ the code may be compiled for different platforms, or with compilers 
of different limits, use the "portable" integer type (int32_t, uint64_t, 
etc) that meets (or exceeds) the variable's range.

Once you've made this decision, be prepared to modify it based on 
performance testing and modelling.

-- 
Lew Pitcher
"In Skills We Trust"

[toc] | [prev] | [next] | [standalone]


#169262

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-02-13 10:48 -0800
Message-ID<f018f931-df84-46a5-822f-51497f4caaecn@googlegroups.com>
In reply to#169256
On Monday, 13 February 2023 at 15:19:04 UTC, Steve Summit wrote:
> In its very first question, the FAQ list currently says: 
> 
> If you might need large values (above 32,767 or 
> below -32,767), use long. Otherwise, if space is 
> very important (i.e. if there are large arrays or 
> many structures), use short. Otherwise, use int. 
> If well-defined overflow characteristics are important 
> and negative values are not, or if you want to steer 
> clear of sign-extension problems when manipulating bits 
> or bytes, use one of the corresponding unsigned types. 
> (Beware when mixing signed and unsigned values in 
> expressions, though; see question 3.19.) 
> 
> Although character types (especially unsigned char) can 
> be used as ``tiny'' integers, doing so is sometimes more 
> trouble than it's worth. The compiler will have to emit 
> extra code to convert between char and int (making the 
> executable larger), and unexpected sign extension can be 
> troublesome. (Using unsigned char can help; see question 
> 12.1 for a related problem.) 
> 
> A similar space/time tradeoff applies when deciding 
> between float and double. (Many compilers still convert 
> all float values to double during expression evaluation.) 
> 
> ...If for some reason you need to declare something with 
> an exact size (usually the only good reason for doing so 
> is when attempting to conform to some externally-imposed 
> storage layout, but see question 20.5), be sure to 
> encapsulate the choice behind an appropriate typedef, 
> but see question 1.3. 
> 
> Besides cleaning up the wording (this answer, like much of my 
> writing, is afflicted with Too Many Parentheticals :-) ), I am 
> strongly considering making one or two additional, potentially 
> controversial points: 
> 
> If you want to make the considered assumption that your 
> code will only ever run on "modern" hardware, you can say 
> that plain int can hold up to +-2147483647 (that is, has 
> 32 bits). 
> 
> Some coding guidelines, notably MISRA, deprecate the 
> "abstract" types short, int, and long, and mandate always 
> using exact-size types like int16_t and int32_t. 
> 
> To the first point, believe me, I do know what the Standard 
> guarantees about type int, and I remember well the pejorative 
> phrase "All the world's a VAX" as promulgated in, among other 
> things, Henry Spencer's 10 Commandments. But I also know that 
> the codebase I work on every day in my day job makes this 
> assumption, and I'm pretty sure I'm not alone. 
> 
> To the second point, while I personally disagree up, down, and 
> sideways with the dictum "don't use plain int", I can't ignore the 
> fact that many practicing C programmers do advocate and follow it, 
> and many projects faithfully honor MISRA. 
> 
> Opinions (in support or denigration of either point) welcome. 
> 
As a general rule data is real, though of course quantised for measuring
and representation reasons, whilst the integers in the program represent 
either counts of data elements, or indices into arrays of data. That's only
a general rule, of course, and it's possible to devise a program which works
mainly on discrete data.
size_t was designed to hold a size in bytes of memory. But it quickly became
extended to holding a count of obhjects in memory. Which means that an index
needs to be a size_t. Which means that if you are consistent, then almost
all the integers in the program will be size_ts.
However few people are consistent. People don't like using a type named "size_t"
to hold something which isn't a size. And intermediate index values can go negative,
for example when applying a windowed filter to an array. And, because size_t
can hold the szie of any object, it has to be wide enough to hold the 
largest object the system can create, which typically means it needs to be
64 bits. This wastes memory and, more importantly, cache.

However there's no agreement about how to solve this problem. Instead the
committee has introduced more standard integer types. Which is asking for
problems when types resolve to the same underlying machine instructions
on the test architecture, and different underlying machine instructions on
the deployment architecture.

[toc] | [prev] | [next] | [standalone]


#169264

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-02-14 03:10 +0000
Message-ID<20230213190727.848@kylheku.com>
In reply to#169256
On 2023-02-13, Steve Summit <scs@eskimo.com> wrote:
> 	Some coding guidelines, notably MISRA, deprecate the
> 	"abstract" types short, int, and long, and mandate always
> 	using exact-size types like int16_t and int32_t.

In that MISRAble industry, it's acceptable for mechanically sound
automobiles to be scrapped due to software obsolescence.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca

[toc] | [prev] | [next] | [standalone]


#169270

FromBlue-Maned_Hawk <bluemanedhawk@gmail.com>
Date2023-02-14 17:33 -0500
Message-ID<tsh275$2l2ps$3@bluemanedhawk.eternal-september.org>
In reply to#169264
On 2/13/23 22:10, Kaz Kylheku wrote:
> On 2023-02-13, Steve Summit <scs@eskimo.com> wrote:
>> 	Some coding guidelines, notably MISRA, deprecate the
>> 	"abstract" types short, int, and long, and mandate always
>> 	using exact-size types like int16_t and int32_t.
> 
> In that MISRAble industry, it's acceptable for mechanically sound
> automobiles to be scrapped due to software obsolescence.
> 

Does that bear any direct relation to the exact-width type requirements?

-- 
⚗︎ | /blu.mɛin.dʰak/ | shortens to "Hawk" | he/him/his/himself/Mr.
bluemanedhawk.github.io
Bitches stole my whole ass ␔🭖᷿᪳𝼗᷍⏧𒒫𐻾ࣛ↉�⃣ quoted-printable, can't 
have shit in Thunderbird 😩

[toc] | [prev] | [next] | [standalone]


#169266

FromÖö Tiib <ootiib@hot.ee>
Date2023-02-13 23:24 -0800
Message-ID<5281302c-69cb-447f-890f-a8bf31882d5fn@googlegroups.com>
In reply to#169256
On Monday, 13 February 2023 at 17:19:04 UTC+2, Steve Summit wrote:
> In its very first question, the FAQ list currently says: 
> 
> If you might need large values (above 32,767 or 
> below -32,767), use long. Otherwise, if space is 
> very important (i.e. if there are large arrays or 
> many structures), use short. Otherwise, use int. 
> If well-defined overflow characteristics are important 
> and negative values are not, or if you want to steer 
> clear of sign-extension problems when manipulating bits 
> or bytes, use one of the corresponding unsigned types. 
> (Beware when mixing signed and unsigned values in 
> expressions, though; see question 3.19.) 
> 
> Although character types (especially unsigned char) can 
> be used as ``tiny'' integers, doing so is sometimes more 
> trouble than it's worth. The compiler will have to emit 
> extra code to convert between char and int (making the 
> executable larger), and unexpected sign extension can be 
> troublesome. (Using unsigned char can help; see question 
> 12.1 for a related problem.) 
> 
> A similar space/time tradeoff applies when deciding 
> between float and double. (Many compilers still convert 
> all float values to double during expression evaluation.) 
> 
> ...If for some reason you need to declare something with 
> an exact size (usually the only good reason for doing so 
> is when attempting to conform to some externally-imposed 
> storage layout, but see question 20.5), be sure to 
> encapsulate the choice behind an appropriate typedef, 
> but see question 1.3. 
> 
> Besides cleaning up the wording (this answer, like much of my 
> writing, is afflicted with Too Many Parentheticals :-) ), I am 
> strongly considering making one or two additional, potentially 
> controversial points: 
> 
> If you want to make the considered assumption that your 
> code will only ever run on "modern" hardware, you can say 
> that plain int can hold up to +-2147483647 (that is, has 
> 32 bits). 
> 
> Some coding guidelines, notably MISRA, deprecate the 
> "abstract" types short, int, and long, and mandate always 
> using exact-size types like int16_t and int32_t. 
> 
> To the first point, believe me, I do know what the Standard 
> guarantees about type int, and I remember well the pejorative 
> phrase "All the world's a VAX" as promulgated in, among other 
> things, Henry Spencer's 10 Commandments. But I also know that 
> the codebase I work on every day in my day job makes this 
> assumption, and I'm pretty sure I'm not alone. 
> 
> To the second point, while I personally disagree up, down, and 
> sideways with the dictum "don't use plain int", I can't ignore the 
> fact that many practicing C programmers do advocate and follow it, 
> and many projects faithfully honor MISRA. 
> 
> Opinions (in support or denigration of either point) welcome. 
> 
The reason of those coding guidelines is that world is more
inter-connected and also individual devices consist of bigger
number of subsystems. Exact size is needed for communicating;
code with exact size types simplifies replacing subsystems.

[toc] | [prev] | [next] | [standalone]


#169267

Frombart c <bart4858@gmail.com>
Date2023-02-14 06:22 -0800
Message-ID<2e1d44fe-bd17-47ea-b4c9-90a541af1febn@googlegroups.com>
In reply to#169256
On Monday, 13 February 2023 at 15:19:04 UTC, Steve Summit wrote:
> In its very first question, the FAQ list currently says: 
> 
>" If you might need large values (above 32,767 or 
> below -32,767), use long."

> Besides cleaning up the wording (this answer, like much of my 
> writing, is afflicted with Too Many Parentheticals :-) ), I am 
> strongly considering making one or two additional, potentially 
> controversial points: 
> 
> If you want to make the considered assumption that your 
> code will only ever run on "modern" hardware, you can say 
> that plain int can hold up to +-2147483647 (that is, has 
> 32 bits). 

That description /is/ dated, and yet C does say that `int` is only guaranteed to be 16 bits.

But if you leave it, it will be suggested that everybody uses 'long' instead, which has its own problems, like varying in size between 32-bit and 64-bit Linux, so you might end up with a 64-bit value, when the requirement was no more than 32 bits.


> Some coding guidelines, notably MISRA, deprecate the 
> "abstract" types short, int, and long, and mandate always 
> using exact-size types like int16_t and int32_t. 

Which have yet more problems of their own, since the rest of the languge doesn't recogniss those as native types; you still use:

    printf("%ld",a);
    123LL
    123           Has a maximum value of INT_MAX, whatever int happens to be

I don't have any suggestions; you will have your work cut out. I've long thought C's type system is messy, and wouldn't relish documenting it, let alone offer advice given the vast range of hardware the language can be used on.


> To the first point, believe me, I do know what the Standard 
> guarantees about type int, and I remember well the pejorative 
> phrase "All the world's a VAX" as promulgated in, among other 
> things, Henry Spencer's 10 Commandments. But I also know that 
> the codebase I work on every day in my day job makes this 
> assumption, and I'm pretty sure I'm not alone. 
> 
> To the second point, while I personally disagree up, down, and 
> sideways with the dictum "don't use plain int", I can't ignore the 
> fact that many practicing C programmers do advocate and follow it, 

Plain int was a "don't care" type. It could be assumed to be sufficiently wide enough to match the scale of machine. But for a long time it has actually been too small for that purpose.

I normally use my languages where default 'int' has been 64-bits for a decade. That really is "don't care", as it can accommodate most things: RAM capacity, array sizes, disk capacity, file sizes...

But a huge amount of C code still uses plain 'int', and most implementations, outside of microcontrollers, have it as 32-bits, even though the dominant hardware is 64-bit. Care needs to be taken, and signed overflow is distinct possibility.

[toc] | [prev] | [next] | [standalone]


#169271

FromBlue-Maned_Hawk <bluemanedhawk@gmail.com>
Date2023-02-14 17:48 -0500
Message-ID<tsh333$2l2pt$1@bluemanedhawk.eternal-september.org>
In reply to#169267
On 2/14/23 09:22, bart c wrote:
> On Monday, 13 February 2023 at 15:19:04 UTC, Steve Summit wrote:
> 
> [snip]
> 
>> Some coding guidelines, notably MISRA, deprecate the
>> "abstract" types short, int, and long, and mandate always
>> using exact-size types like int16_t and int32_t.
> 
> Which have yet more problems of their own, since the rest of the languge doesn't recogniss those as native types; you still use:
> 
>      printf("%ld",a);
>  > [snip]

​For that particular discrepancy, the <inttypes.h> header has macros 
that expand to strings literals which correspond to the appropriate 
specifier sequence, and C23 will introduce the `%w𝑁` and `%wf𝑁` length 
modifiers.  Strangely, the latter isn't required to work with arbitrary 
`_BitInt()` types, despite C23 introducing those as well.

-- 
⚗︎ | /blu.mɛin.dʰak/ | shortens to "Hawk" | he/him/his/himself/Mr.
bluemanedhawk.github.io
Bitches stole my whole ass ␔🭖᷿᪳𝼗᷍⏧𒒫𐻾ࣛ↉�⃣ quoted-printable, can't 
have shit in Thunderbird 😩

[toc] | [prev] | [next] | [standalone]


#169268

FromJohn Dill <jadill33@gmail.com>
Date2023-02-14 08:17 -0800
Message-ID<a4d79dc0-db6d-4a94-9a52-fb603d75f1ccn@googlegroups.com>
In reply to#169256
On Monday, February 13, 2023 at 10:19:04 AM UTC-5, Steve Summit wrote:
> In its very first question, the FAQ list currently says: 
> 
> If you might need large values (above 32,767 or 
> below -32,767), use long. Otherwise, if space is 
> very important (i.e. if there are large arrays or 
> many structures), use short. Otherwise, use int. 
> If well-defined overflow characteristics are important 
> and negative values are not, or if you want to steer 
> clear of sign-extension problems when manipulating bits 
> or bytes, use one of the corresponding unsigned types. 
> (Beware when mixing signed and unsigned values in 
> expressions, though; see question 3.19.) 
> 
> Although character types (especially unsigned char) can 
> be used as ``tiny'' integers, doing so is sometimes more 
> trouble than it's worth. The compiler will have to emit 
> extra code to convert between char and int (making the 
> executable larger), and unexpected sign extension can be 
> troublesome. (Using unsigned char can help; see question 
> 12.1 for a related problem.) 
> 
> A similar space/time tradeoff applies when deciding 
> between float and double. (Many compilers still convert 
> all float values to double during expression evaluation.) 
> 
> ...If for some reason you need to declare something with 
> an exact size (usually the only good reason for doing so 
> is when attempting to conform to some externally-imposed 
> storage layout, but see question 20.5), be sure to 
> encapsulate the choice behind an appropriate typedef, 
> but see question 1.3. 
> 
> Besides cleaning up the wording (this answer, like much of my 
> writing, is afflicted with Too Many Parentheticals :-) ), I am 
> strongly considering making one or two additional, potentially 
> controversial points: 
> 
> If you want to make the considered assumption that your 
> code will only ever run on "modern" hardware, you can say 
> that plain int can hold up to +-2147483647 (that is, has 
> 32 bits). 
> 
> Some coding guidelines, notably MISRA, deprecate the 
> "abstract" types short, int, and long, and mandate always 
> using exact-size types like int16_t and int32_t. 
> 
> To the first point, believe me, I do know what the Standard 
> guarantees about type int, and I remember well the pejorative 
> phrase "All the world's a VAX" as promulgated in, among other 
> things, Henry Spencer's 10 Commandments. But I also know that 
> the codebase I work on every day in my day job makes this 
> assumption, and I'm pretty sure I'm not alone. 
> 
> To the second point, while I personally disagree up, down, and 
> sideways with the dictum "don't use plain int", I can't ignore the 
> fact that many practicing C programmers do advocate and follow it, 
> and many projects faithfully honor MISRA. 
> 
> Opinions (in support or denigration of either point) welcome. 

I'll chime in to provide one sample programmer to your pool.  I work
in avionics with a combination of largely Ada and C.

I tend to use int when there is an apriori established pattern of usage
in the standard library, with the most common examples of using 'int'
are as a return value, e.g.

int date_compare( struct date d1, struct date d2 );

or as a generic character, e.g. 'fputc'.

Usage of int as a general storage class is rare in my area of development
which focuses on unambiguous sizes for storage.  This is required for
defining interfaces of communication using either files or network
structured records.  However, 'int' may be used as a signed count whose
physical storage size is likely to be unimportant, e.g.

struct c_greg_date c_date_add_weeks( struct c_greg_date date, int weeks );

I fall into the size_t camp (instead of 'int') for common looping of unsigned
sequences.  For size_t values where a -1 is needed for semantics, we use
a preprocessor sequence to generate a signed version of size_t called
ssize_t.

I prefer 'bool' over 'int' for boolean constructs in APIs.

I heavily typedef integer types for implicitly attributing additional semantics
to the integer storage type.  I heavily use constraint checking in APIs to
validate integer ranges (and parameters in general).  Here's a example of
the style (this function just happened to have a lot of constraint checking).

\code
struct c_greg_date c_partial_date( c_greg_year year,
                                   c_greg_month month,
                                   c_greg_day day )
{
  struct c_greg_date date;

  c_return_value_if_fail( year >= 0, gc_invalid_greg_date );
  c_return_value_if_fail( month >= 0 && month <= C_DECEMBER, gc_invalid_greg_date );
  if ( year != 0 && month != 0 ) {
    c_return_value_if_fail( day >= 0 && day <= c_days_in_month( month, year ), gc_invalid_greg_date );
  } else {
    c_return_value_if_fail( day >= 0 && day <= 31, gc_invalid_greg_date );
  }

  date.year = year;
  date.month = month;
  date.day = day;

  return date;
}
\endcode

The macro c_return_value_if_fail can be configured to print or log a
diagnostic when enabled, showing when constraints are broken.

I'm heavily tainted by working with Ada for almost a decade, so keep that
in mind.

Best regards,
John D.

[toc] | [prev] | [next] | [standalone]


#169269

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2023-02-14 12:34 -0800
Message-ID<87ttzoq943.fsf@nosuchdomain.example.com>
In reply to#169268
John Dill <jadill33@gmail.com> writes:
[...]
> I fall into the size_t camp (instead of 'int') for common looping of unsigned
> sequences.  For size_t values where a -1 is needed for semantics, we use
> a preprocessor sequence to generate a signed version of size_t called
> ssize_t.
[...]

POSIX defines a type ssize_t, a signed type that may or may not be the
signed type corresponding to size_t.  It's defined in <sys/types.h> and
other headers.  If there's any chance of your code being compiled under
POSIX, you might consider checking whether SSIZE_T is defined, and if so
just use the POSIX ssize_t (and be aware that it might not be the signed
type corresponding to size_t).  Or pick a different name for your type.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#169277

FromJohn Dill <jadill33@gmail.com>
Date2023-02-15 10:04 -0800
Message-ID<fb2a9938-72f1-438b-95de-ca580431f1e3n@googlegroups.com>
In reply to#169269
On Tuesday, February 14, 2023 at 3:34:52 PM UTC-5, Keith Thompson wrote:
> John Dill <jadi...@gmail.com> writes: 
> [...]
> > I fall into the size_t camp (instead of 'int') for common looping of unsigned 
> > sequences. For size_t values where a -1 is needed for semantics, we use 
> > a preprocessor sequence to generate a signed version of size_t called 
> > ssize_t.
> [...] 
> 
> POSIX defines a type ssize_t, a signed type that may or may not be the 
> signed type corresponding to size_t. It's defined in <sys/types.h> and 
> other headers. If there's any chance of your code being compiled under 
> POSIX, you might consider checking whether SSIZE_T is defined, and if so 
> just use the POSIX ssize_t (and be aware that it might not be the signed 
> type corresponding to size_t). Or pick a different name for your type. 

Agreed.  We have something along these lines, with the build system
handling the definitions of the HAVE tests.

We lean on POSIX whenever possible, but not all environments support
POSIX.

\code
/* If the <sys/types.h> header file is found, including the file
   should define the 'ssize_t' type. */
#if defined(HAVE_SYS_TYPES_H)
#  include <sys/types.h>
#else
#  if !defined(HAVE_SSIZE_T)
     /*
      * The best candidate to define 'ssize_t' is 'ptrdiff_t'.  If
      * 'ptrdiff_t' is not found, then the fallback type will be
      * 'long int'.
      */
#    if defined(PTRDIFF_MAX)
       typedef ptrdiff_t ssize_t;
#    else
       typedef long int ssize_t;
#    endif
#  endif
#endif
C_STATIC_ASSERT (sizeof (ssize_t) == sizeof (size_t),
                 ssize_t_is_compatible_with_size_t);
\endcode

Best regards,
John D.

[toc] | [prev] | [next] | [standalone]


#169278

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2023-02-15 10:28 -0800
Message-ID<87pmaarden.fsf@nosuchdomain.example.com>
In reply to#169277
John Dill <jadill33@gmail.com> writes:
> On Tuesday, February 14, 2023 at 3:34:52 PM UTC-5, Keith Thompson wrote:
>> John Dill <jadi...@gmail.com> writes: 
>> [...]
>> > I fall into the size_t camp (instead of 'int') for common looping of unsigned 
>> > sequences. For size_t values where a -1 is needed for semantics, we use 
>> > a preprocessor sequence to generate a signed version of size_t called 
>> > ssize_t.
>> [...] 
>> 
>> POSIX defines a type ssize_t, a signed type that may or may not be the 
>> signed type corresponding to size_t. It's defined in <sys/types.h> and 
>> other headers. If there's any chance of your code being compiled under 
>> POSIX, you might consider checking whether SSIZE_T is defined, and if so 
>> just use the POSIX ssize_t (and be aware that it might not be the signed 
>> type corresponding to size_t). Or pick a different name for your type. 
>
> Agreed.  We have something along these lines, with the build system
> handling the definitions of the HAVE tests.
>
> We lean on POSIX whenever possible, but not all environments support
> POSIX.
>
> \code
> /* If the <sys/types.h> header file is found, including the file
>    should define the 'ssize_t' type. */
> #if defined(HAVE_SYS_TYPES_H)
> #  include <sys/types.h>
> #else
> #  if !defined(HAVE_SSIZE_T)
>      /*
>       * The best candidate to define 'ssize_t' is 'ptrdiff_t'.  If
>       * 'ptrdiff_t' is not found, then the fallback type will be
>       * 'long int'.
>       */
> #    if defined(PTRDIFF_MAX)
>        typedef ptrdiff_t ssize_t;
> #    else
>        typedef long int ssize_t;
> #    endif
> #  endif
> #endif
> C_STATIC_ASSERT (sizeof (ssize_t) == sizeof (size_t),
>                  ssize_t_is_compatible_with_size_t);
> \endcode

Rather than HAVE_SSIZE_T, you could check whether SSIZE_MAX is
defined in <limits.h>.

ptrdiff_t has been standard since C89/C90.  You can probably
get away with not testing for it.  Note that PTRDIFF_MAX wasn't
introduced until C99, so you could get a false negative on some
old implementations.

An alternative might be to check the values of UINT_MAX, ULONG_MAX,
and ULLONG_MAX vs. SIZE_MAX and use the corresponding signed type
int, long, or long long.  That's if you want to be really picky,
but what you have should work on any realistic target platform.

The name "ssize_t_is_compatible_with_size_t" is a bit misleading.
C type compatibility is defined very narrowly.  A signed type is
never *compatible* with an unsigned type.  What is "compatible"
supposed to mean in this context?

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#169279

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-02-15 10:57 -0800
Message-ID<4803956e-d074-4787-b063-ed0593ca949cn@googlegroups.com>
In reply to#169278
On Wednesday, 15 February 2023 at 18:29:07 UTC, Keith Thompson wrote:
> John Dill <jadi...@gmail.com> writes: 
> > On Tuesday, February 14, 2023 at 3:34:52 PM UTC-5, Keith Thompson wrote: 
> >> John Dill <jadi...@gmail.com> writes: 
> >> [...] 
> >> > I fall into the size_t camp (instead of 'int') for common looping of unsigned 
> >> > sequences. For size_t values where a -1 is needed for semantics, we use 
> >> > a preprocessor sequence to generate a signed version of size_t called 
> >> > ssize_t. 
> >> [...] 
> >> 
> >> POSIX defines a type ssize_t, a signed type that may or may not be the 
> >> signed type corresponding to size_t. It's defined in <sys/types.h> and 
> >> other headers. If there's any chance of your code being compiled under 
> >> POSIX, you might consider checking whether SSIZE_T is defined, and if so 
> >> just use the POSIX ssize_t (and be aware that it might not be the signed 
> >> type corresponding to size_t). Or pick a different name for your type. 
> > 
> > Agreed. We have something along these lines, with the build system 
> > handling the definitions of the HAVE tests. 
> > 
> > We lean on POSIX whenever possible, but not all environments support 
> > POSIX. 
> > 
> > \code 
> > /* If the <sys/types.h> header file is found, including the file 
> > should define the 'ssize_t' type. */ 
> > #if defined(HAVE_SYS_TYPES_H) 
> > # include <sys/types.h> 
> > #else 
> > # if !defined(HAVE_SSIZE_T) 
> > /* 
> > * The best candidate to define 'ssize_t' is 'ptrdiff_t'. If 
> > * 'ptrdiff_t' is not found, then the fallback type will be 
> > * 'long int'. 
> > */ 
> > # if defined(PTRDIFF_MAX) 
> > typedef ptrdiff_t ssize_t; 
> > # else 
> > typedef long int ssize_t; 
> > # endif 
> > # endif 
> > #endif 
> > C_STATIC_ASSERT (sizeof (ssize_t) == sizeof (size_t), 
> > ssize_t_is_compatible_with_size_t); 
> > \endcode
> Rather than HAVE_SSIZE_T, you could check whether SSIZE_MAX is 
> defined in <limits.h>. 
> 
> ptrdiff_t has been standard since C89/C90. You can probably 
> get away with not testing for it. Note that PTRDIFF_MAX wasn't 
> introduced until C99, so you could get a false negative on some 
> old implementations. 
> 
> An alternative might be to check the values of UINT_MAX, ULONG_MAX, 
> and ULLONG_MAX vs. SIZE_MAX and use the corresponding signed type 
> int, long, or long long. That's if you want to be really picky, 
> but what you have should work on any realistic target platform. 
> 
> The name "ssize_t_is_compatible_with_size_t" is a bit misleading. 
> C type compatibility is defined very narrowly. A signed type is 
> never *compatible* with an unsigned type. What is "compatible" 
> supposed to mean in this context?
> 
It means that the binary representation of the unsigned type is the same
as the binary representation of the signed type when it is non-negative.

So 
ssize_t ssz;
size_t sz = sizeof(int);
ssz = *(ssize_t *) &sz;

puts sizeof(int) into ssz;

[toc] | [prev] | [next] | [standalone]


#169281

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2023-02-15 11:17 -0800
Message-ID<87lekyrb4z.fsf@nosuchdomain.example.com>
In reply to#169279
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
> On Wednesday, 15 February 2023 at 18:29:07 UTC, Keith Thompson wrote:
[...]
>> The name "ssize_t_is_compatible_with_size_t" is a bit misleading. 
>> C type compatibility is defined very narrowly. A signed type is 
>> never *compatible* with an unsigned type. What is "compatible" 
>> supposed to mean in this context?
>> 
> It means that the binary representation of the unsigned type is the same
> as the binary representation of the signed type when it is non-negative.
>
> So 
> ssize_t ssz;
> size_t sz = sizeof(int);
> ssz = *(ssize_t *) &sz;
>
> puts sizeof(int) into ssz;

That's not what "compatible" means in C.  I asked what the code John
Dill posted meant by "compatible".  Are you familiar with that code,
including parts that haven't been posted?

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#169283

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2023-02-15 11:32 -0800
Message-ID<87a61erag6.fsf@nosuchdomain.example.com>
In reply to#169281
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
> Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
>> On Wednesday, 15 February 2023 at 18:29:07 UTC, Keith Thompson wrote:
> [...]
>>> The name "ssize_t_is_compatible_with_size_t" is a bit misleading. 
>>> C type compatibility is defined very narrowly. A signed type is 
>>> never *compatible* with an unsigned type. What is "compatible" 
>>> supposed to mean in this context?
>>> 
>> It means that the binary representation of the unsigned type is the same
>> as the binary representation of the signed type when it is non-negative.
>>
>> So 
>> ssize_t ssz;
>> size_t sz = sizeof(int);
>> ssz = *(ssize_t *) &sz;
>>
>> puts sizeof(int) into ssz;
>
> That's not what "compatible" means in C.  I asked what the code John
> Dill posted meant by "compatible".  Are you familiar with that code,
> including parts that haven't been posted?

I think I misread the code.  `sizeof (ssize_t) == sizeof (size_t)` is
the condition being asserted, and `size_t_is_compatible_with_size_t` is
the name associated with that assertion, not something that's defined
elsewhere.

ssize_t and size_t being the same size does not guarantee that the
binary representations are the same for common values.  That's
guaranteed only if they are corresponding signed and unsigned types,
like long and unsigned long.  Their representations are very likely to
match, but unless the code does some odd low-level stuff that's unlikely
to matter.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#169280

FromJohn Dill <jadill33@gmail.com>
Date2023-02-15 11:01 -0800
Message-ID<bc0d6df6-1856-4518-8d7d-f3d7febabaecn@googlegroups.com>
In reply to#169278
On Wednesday, February 15, 2023 at 1:29:07 PM UTC-5, Keith Thompson wrote:
> John Dill <jadi...@gmail.com> writes: 
> > On Tuesday, February 14, 2023 at 3:34:52 PM UTC-5, Keith Thompson wrote: 
> >> John Dill <jadi...@gmail.com> writes: 
> >> [...] 
> >> > I fall into the size_t camp (instead of 'int') for common looping of unsigned 
> >> > sequences. For size_t values where a -1 is needed for semantics, we use 
> >> > a preprocessor sequence to generate a signed version of size_t called 
> >> > ssize_t. 
> >> [...] 
> >> 
> >> POSIX defines a type ssize_t, a signed type that may or may not be the 
> >> signed type corresponding to size_t. It's defined in <sys/types.h> and 
> >> other headers. If there's any chance of your code being compiled under 
> >> POSIX, you might consider checking whether SSIZE_T is defined, and if so 
> >> just use the POSIX ssize_t (and be aware that it might not be the signed 
> >> type corresponding to size_t). Or pick a different name for your type. 
> > 
> > Agreed. We have something along these lines, with the build system 
> > handling the definitions of the HAVE tests. 
> > 
> > We lean on POSIX whenever possible, but not all environments support 
> > POSIX. 
> > 
> > \code 
> > /* If the <sys/types.h> header file is found, including the file 
> > should define the 'ssize_t' type. */ 
> > #if defined(HAVE_SYS_TYPES_H) 
> > # include <sys/types.h> 
> > #else 
> > # if !defined(HAVE_SSIZE_T) 
> > /* 
> > * The best candidate to define 'ssize_t' is 'ptrdiff_t'. If 
> > * 'ptrdiff_t' is not found, then the fallback type will be 
> > * 'long int'. 
> > */ 
> > # if defined(PTRDIFF_MAX) 
> > typedef ptrdiff_t ssize_t; 
> > # else 
> > typedef long int ssize_t; 
> > # endif 
> > # endif 
> > #endif 
> > C_STATIC_ASSERT (sizeof (ssize_t) == sizeof (size_t), 
> > ssize_t_is_compatible_with_size_t); 
> > \endcode
> Rather than HAVE_SSIZE_T, you could check whether SSIZE_MAX is 
> defined in <limits.h>. 

Having the test be compiler local instead of autoconf style generated
has its appeal.

> ptrdiff_t has been standard since C89/C90. You can probably 
> get away with not testing for it. Note that PTRDIFF_MAX wasn't 
> introduced until C99, so you could get a false negative on some 
> old implementations. 

Nice find!

> An alternative might be to check the values of UINT_MAX, ULONG_MAX, 
> and ULLONG_MAX vs. SIZE_MAX and use the corresponding signed type 
> int, long, or long long. That's if you want to be really picky, 
> but what you have should work on any realistic target platform. 

I appreciate really picky.

> The name "ssize_t_is_compatible_with_size_t" is a bit misleading. 
> C type compatibility is defined very narrowly. A signed type is 
> never *compatible* with an unsigned type. What is "compatible" 
> supposed to mean in this context?

That's a good point.  A better term is "size equivalent" perhaps?

Really appreciate the thoughts.

Cheers!
John D.

[toc] | [prev] | [next] | [standalone]


#169282

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2023-02-15 11:28 -0800
Message-ID<87edqqranm.fsf@nosuchdomain.example.com>
In reply to#169280
John Dill <jadill33@gmail.com> writes:
> On Wednesday, February 15, 2023 at 1:29:07 PM UTC-5, Keith Thompson wrote:
>> John Dill <jadi...@gmail.com> writes: 
[...]
>> > C_STATIC_ASSERT (sizeof (ssize_t) == sizeof (size_t), 
>> > ssize_t_is_compatible_with_size_t); 
>> > \endcode
[...]
>> The name "ssize_t_is_compatible_with_size_t" is a bit misleading. 
>> C type compatibility is defined very narrowly. A signed type is 
>> never *compatible* with an unsigned type. What is "compatible" 
>> supposed to mean in this context?
>
> That's a good point.  A better term is "size equivalent" perhaps?

I misread the arguments to the C_STATIC_ASSERT() macro; I thought you
were testing two different conditions.  I see that
    sizeof (ssize_t) == sizeof (size_t)
is the condition being tested, and
    size_t_is_compatible_with_size_t
is a name assigned to that condition (used in an error message?).

How about "size_t_ssize_t_same_size"?  (Yeah, it's a bit ugly.)

But is that really a requirement?  Note that POSIX doesn't guarantee
that size_t and ssize_t have the same size.  I'd be surprised by an
implementation in which their sizes differ.  But if size_t and ssize_t
are the same size, then there will be sizes representable as a size_t
that exceed SSIZE_MAX; if that's a problem for real code, an
implementation might make ssize_t bigger than size_t.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web