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


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

Malloc Query

Started byPushpa <pushpa@nospam.invalid>
First post2011-05-17 19:39 +0000
Last post2011-05-19 09:12 -0600
Articles 20 on this page of 92 — 26 participants

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


Contents

  Malloc Query Pushpa <pushpa@nospam.invalid> - 2011-05-17 19:39 +0000
    Re: Malloc Query blp@cs.stanford.edu (Ben Pfaff) - 2011-05-17 12:55 -0700
      Re: Malloc Query "BartC" <bc@freeuk.com> - 2011-05-18 12:05 +0100
        Re: Malloc Query Pushpa <pushpa@nospam.invalid> - 2011-05-18 17:11 +0000
          Re: Malloc Query "BartC" <bc@freeuk.com> - 2011-05-18 22:42 +0100
          Re: Malloc Query Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-05-18 21:10 -0400
        Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-18 19:34 +0100
          Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-18 17:10 -0400
            Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-19 00:26 +0100
              Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-18 21:25 -0400
                Re: Malloc Query James Kuyper <jameskuyper@verizon.net> - 2011-05-18 21:38 -0400
                  Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-19 14:11 -0400
                    Re: Malloc Query James Kuyper <jameskuyper@verizon.net> - 2011-05-19 22:55 -0400
                      Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-20 12:14 -0400
                Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-19 03:22 +0100
                  Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-19 14:20 -0400
                    Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-19 23:51 +0100
                      Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-19 20:01 -0400
                    Re: Malloc Query luser- -droog <mijoryx@yahoo.com> - 2011-05-22 02:49 -0700
                      Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-22 10:46 -0400
                        Re: Malloc Query Shao Miller <sha0.miller@gmail.com> - 2011-05-22 12:37 -0500
                          Re: Malloc Query Shao Miller <sha0.miller@gmail.com> - 2011-05-22 13:02 -0500
                          Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-22 14:12 -0400
                            Re: Malloc Query Shao Miller <sha0.miller@gmail.com> - 2011-05-23 03:06 -0500
                              Re: Malloc Query luser- -droog <mijoryx@yahoo.com> - 2011-05-23 00:42 -0700
                              Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-23 11:10 -0400
                                Re: Malloc Query Keith Thompson <kst-u@mib.org> - 2011-05-23 09:06 -0700
                        Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-22 23:18 +0100
                          Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-22 19:18 -0400
                            Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-23 11:22 +1200
                              Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-23 01:57 -0400
                                Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-23 19:24 +1200
                                  Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-23 14:20 -0400
                                    Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-24 07:41 +1200
                                      Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-23 16:24 -0400
                                        Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-24 09:20 +1200
                                          Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-23 18:05 -0400
                                            Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-24 10:37 +1200
                                              Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-23 19:34 -0400
                                      Re: Malloc Query "robertwessel2@yahoo.com" <robertwessel2@yahoo.com> - 2011-05-23 17:48 -0700
                                        Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-24 12:56 +1200
                                    Re: Malloc Query James Kuyper <jameskuyper@verizon.net> - 2011-05-24 07:19 -0400
                                      Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-24 11:32 -0400
                            Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-23 01:04 +0100
                              Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-23 02:36 -0400
                                Re: Malloc Query luser- -droog <mijoryx@yahoo.com> - 2011-05-23 00:39 -0700
                                Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-23 14:44 +0100
                                  Re: Malloc Query Seebs <usenet-nospam@seebs.net> - 2011-05-23 15:16 +0000
                                  Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-23 11:41 -0400
                                  Re: Malloc Query David Thompson <dave.thompson2@verizon.net> - 2011-06-01 16:33 -0400
                  Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-19 18:34 -0400
                    Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-20 02:36 +0100
                      Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-20 12:26 -0400
                        Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-20 23:32 +0100
                          Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-20 21:17 -0400
                    Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-21 14:30 +1200
                      Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-21 11:13 -0400
                        Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-22 08:50 +1200
                          Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-21 20:03 -0400
                            Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-22 13:23 +1200
                              Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-22 10:01 -0400
                    Re: Malloc Query "io_x" <a@b.c.invalid> - 2011-05-26 08:12 +0200
                      Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-26 19:16 +1200
                        Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-26 15:03 -0400
                          Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-27 09:16 +1200
                            Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-26 17:55 -0400
                          Re: Malloc Query "io_x" <a@b.c.invalid> - 2011-05-27 05:47 +0200
                      Re: Malloc Query Uncle Steve <stevet810@gmail.com> - 2011-05-26 15:02 -0400
          Re: Malloc Query "BartC" <bc@freeuk.com> - 2011-05-18 22:31 +0100
            Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-18 23:37 +0100
              Re: Malloc Query "BartC" <bc@freeuk.com> - 2011-05-19 01:50 +0100
                Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-19 02:50 +0100
                  Re: Malloc Query "BartC" <bc@freeuk.com> - 2011-05-19 12:14 +0100
                    Re: Malloc Query Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-05-19 15:10 +0100
                      Re: Malloc Query "BartC" <bc@freeuk.com> - 2011-05-19 15:48 +0100
        Re: Malloc Query cri@tiac.net (Richard Harter) - 2011-05-18 19:31 +0000
        Re: Malloc Query Ike Naar <ike@iceland.freeshell.org> - 2011-05-18 21:43 +0000
          Re: Malloc Query "BartC" <bc@freeuk.com> - 2011-05-18 22:58 +0100
    Re: Malloc Query Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2011-05-17 14:01 -0600
    Re: Malloc Query Columbus sailed the ocean China Blue <chine.bleu@yahoo.com> - 2011-05-17 13:21 -0700
    Re: Malloc Query BGB <cr88192@hotmail.com> - 2011-05-17 14:08 -0700
      Re: Malloc Query Michael Press <rubrum@pacbell.net> - 2011-05-17 19:49 -0700
    Re: Malloc Query Lauri Alanko <la@iki.fi> - 2011-05-18 00:50 +0000
    Re: Malloc Query Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-05-17 21:21 -0400
      Re: Malloc Query "io_x" <a@b.c.invalid> - 2011-05-18 19:31 +0200
      Re: Malloc Query Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-05-18 21:36 +0000
        Re: Malloc Query Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-05-18 21:26 -0400
      Re: Malloc Query Tim Rentsch <txr@alumni.caltech.edu> - 2011-05-19 02:07 -0700
        Re: Malloc Query Ian Collins <ian-news@hotmail.com> - 2011-05-19 21:13 +1200
    Re: Malloc Query Nobody <nobody@nowhere.com> - 2011-05-18 07:08 +0100
    Re: Malloc Query David Resnick <lndresnick@gmail.com> - 2011-05-19 07:51 -0700
      Re: Malloc Query Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2011-05-19 09:12 -0600

Page 3 of 5 — ← Prev page 1 2 [3] 4 5  Next page →


#4640

FromIan Collins <ian-news@hotmail.com>
Date2011-05-24 12:56 +1200
Message-ID<940e1nFt2pU19@mid.individual.net>
In reply to#4639
On 05/24/11 12:48 PM, robertwessel2@yahoo.com wrote:
> On May 23, 2:41 pm, Ian Collins<ian-n...@hotmail.com>  wrote:
>> On 05/24/11 06:20 AM, Uncle Steve wrote:
>>
>>> On Mon, May 23, 2011 at 07:24:11PM +1200, Ian Collins wrote:
>>>> On 05/23/11 05:57 PM, Uncle Steve wrote:
>>
>>>>> For my purposes, it is
>>>>> sometimes nice to write a macro which uses conditionals to select a
>>>>> particular code path through the macro.  If the conditional can be
>>>>> resolved at compile-time, the dead code branches in the macro are
>>>>> pruned, saving space.  A similarly structured function call won't be
>>>>> optimized in this fashion unless (maybe) it is inlined.
>>
>>>> Why not?  Whether the function is called or in line, the conditional
>>>> compiles are still there.
>>
>>> A function is only inlined if it is defined in the same source file.
>>
>> Macros also have to be defined in the same compilation unit.
>>
>>> If you define a function in an external source file, it cannot be
>>> inlined anywhere else unless the function is also defined in an
>>> included header file.  Doesn't everyone know this?
>>
>> I'm sure they do, what's your point?
>
>
> Compilers that support link time code generation manage to inline
> functions defined in different translation units all the time.

I know, see one of my later posts.

-- 
Ian Collins

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


#4687

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-05-24 07:19 -0400
Message-ID<irg480$pfj$1@dont-email.me>
In reply to#4571
On 05/23/2011 02:20 PM, Uncle Steve wrote:
> On Mon, May 23, 2011 at 07:24:11PM +1200, Ian Collins wrote:
>> On 05/23/11 05:57 PM, Uncle Steve wrote:
...
>>> For my purposes, it is
>>> sometimes nice to write a macro which uses conditionals to select a
>>> particular code path through the macro.  If the conditional can be
>>> resolved at compile-time, the dead code branches in the macro are
>>> pruned, saving space.  A similarly structured function call won't be
>>> optimized in this fashion unless (maybe) it is inlined.
>>
>> Why not?  Whether the function is called or in line, the conditional 
>> compiles are still there.
> 
> A function is only inlined if it is defined in the same source file.

Not quite - it only has to be in the same translation unit. A
translation unit consists of a given source file plus all of the other
files merged into it by #include statements. The use of the function
must also occur within the scope of the inline declaration, which
basically means that the declaration should occur prior to the use.
These requirements also apply to macros, though the scope rules are a
bit different for them.

> If you define a function in an external source file, it cannot be
> inlined anywhere else unless the function is also defined in an
> included header file.  Doesn't everyone know this?

If you replace your function-like macro, wherever it is that you have it
defined, with an inline function definition in that same location, that
function will be usable pretty much wherever the the macro was usable.
It's probably feasible to come up with pathological contexts where a
simple in-place replacement won't work, but such contexts are not the norm.

...
>> Inlining is a very simple optimisation.  You also overlook the opposite 
> 
> No it isn't.

Perhaps not, but it's one that most popular modern compilers do
routinely and very well; that's part of what makes them popular.

>> optimisation - not inlining.  There are situations where a smaller 
>> executable performs better (or even fit the target device!).  The 
> 
> In <a8a6d14a9ed9b70-0c8ce@gmail.com> I wrote:
> 
> 	Whether or not the code is inlined is going to depend more on
> 	whether you are interested in performance or code size.
> 
> Fitting code in some machines' L1 cache is harder with a lot of
> gratuitous inlining, and you also pollute the l2 cache.  Sometimes
> this matters, and sometimes not.  All highly dependent on the
> specifics of the code and platform.

Any decent compiler can be relied upon to take those issues into
consideration when deciding whether or not to inline a function. This is
something it can decide, independently of whether or not the function is
declared inline. As far as actual inlining is concerned, the 'inline'
keyword is only a hint, which a compiler is free to ignore; and it's
perfectly legal for a compiler to decide to inline a function that is
not declared 'inline', as long as doing so doesn't change the observable
behavior. In fact, that was one of the arguments given against the
introducing of the 'inline' keyword. Any static function written to meet
the same special requirements that currently apply to 'inline' functions
could already have been inlined, even if not so declared, so long as the
compiler thought that doing so would be a good idea.

Unless you know a lot more about the target platform than your compiler
does, it's probably best to rely upon it to make inlining decisions.
Defining a function (whether or not you use 'inline') gives it that
option. Defining it as a function-like macro does not - it only allows
inlining. Well, technically, I suppose a sufficiently sophisticated
compiler could perform anti-inlining: recognizing a common code pattern,
and replacing it wherever used with a call to a compiler-generated
function definition. The fact that the common code was the result of a
macro expansion would make it easier to recognize the feasibility of
such an optimization. However, and it seems to me to be a harder
optimization to perform than inlining, and I doubt that it is a common
feature even of the most sophisticated compilers.
-- 
James Kuyper

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


#4699

FromUncle Steve <stevet810@gmail.com>
Date2011-05-24 11:32 -0400
Message-ID<7bfe0ef149bdbdd-a0468@gmail.com>
In reply to#4687
On Tue, May 24, 2011 at 07:19:28AM -0400, James Kuyper wrote:
> On 05/23/2011 02:20 PM, Uncle Steve wrote:
> > On Mon, May 23, 2011 at 07:24:11PM +1200, Ian Collins wrote:
> >> On 05/23/11 05:57 PM, Uncle Steve wrote:
> ...
> >>> For my purposes, it is
> >>> sometimes nice to write a macro which uses conditionals to select a
> >>> particular code path through the macro.  If the conditional can be
> >>> resolved at compile-time, the dead code branches in the macro are
> >>> pruned, saving space.  A similarly structured function call won't be
> >>> optimized in this fashion unless (maybe) it is inlined.
> >>
> >> Why not?  Whether the function is called or in line, the conditional 
> >> compiles are still there.
> > 
> > A function is only inlined if it is defined in the same source file.
> 
> Not quite - it only has to be in the same translation unit. A
> translation unit consists of a given source file plus all of the other
> files merged into it by #include statements. The use of the function
> must also occur within the scope of the inline declaration, which
> basically means that the declaration should occur prior to the use.
> These requirements also apply to macros, though the scope rules are a
> bit different for them.

Sorry, I'm not up on the technical nomenclature pertinent to
compilers.  I *meant* to say 'translation unit', but all my brain had
was 'source file'.
 
> > If you define a function in an external source file, it cannot be
> > inlined anywhere else unless the function is also defined in an
> > included header file.  Doesn't everyone know this?
> 
> If you replace your function-like macro, wherever it is that you have it
> defined, with an inline function definition in that same location, that
> function will be usable pretty much wherever the the macro was usable.
> It's probably feasible to come up with pathological contexts where a
> simple in-place replacement won't work, but such contexts are not the norm.

Agreed.
 
> >> Inlining is a very simple optimisation.  You also overlook the opposite 
> > 
> > No it isn't.
> 
> Perhaps not, but it's one that most popular modern compilers do
> routinely and very well; that's part of what makes them popular.

Inline functions are easy to use, but who can measure the performance
advantage of inlining versus the code size tradeoff?  I have no idea
how to accurately measure and quantify the real advantages, which may
be different for every architecture and application.  I suspect the
trend of blindly setting CFLAGS=-O9, which is not all that uncommon in
makefiles, masks a profound ignorance of what really goes on in a
running program.  I also suspect that the complex interaction of
compile and run-time factors defies simplistic optimization
heuristics.

> >> optimisation - not inlining.  There are situations where a smaller 
> >> executable performs better (or even fit the target device!).  The 
> > 
> > In <a8a6d14a9ed9b70-0c8ce@gmail.com> I wrote:
> > 
> > 	Whether or not the code is inlined is going to depend more on
> > 	whether you are interested in performance or code size.
> > 
> > Fitting code in some machines' L1 cache is harder with a lot of
> > gratuitous inlining, and you also pollute the l2 cache.  Sometimes
> > this matters, and sometimes not.  All highly dependent on the
> > specifics of the code and platform.
> 
> Any decent compiler can be relied upon to take those issues into
> consideration when deciding whether or not to inline a function. This is
> something it can decide, independently of whether or not the function is
> declared inline. As far as actual inlining is concerned, the 'inline'
> keyword is only a hint, which a compiler is free to ignore; and it's
> perfectly legal for a compiler to decide to inline a function that is
> not declared 'inline', as long as doing so doesn't change the observable
> behavior. In fact, that was one of the arguments given against the
> introducing of the 'inline' keyword. Any static function written to meet
> the same special requirements that currently apply to 'inline' functions
> could already have been inlined, even if not so declared, so long as the
> compiler thought that doing so would be a good idea.

At least these compilers allow one to individually tune the
optimization characteristic of the compilation process.  If you don't
want inlining, it's trivial to turn it off.
 
> Unless you know a lot more about the target platform than your compiler
> does, it's probably best to rely upon it to make inlining decisions.

All things being equal, that is decent advice.

> Defining a function (whether or not you use 'inline') gives it that
> option. Defining it as a function-like macro does not - it only allows
> inlining. Well, technically, I suppose a sufficiently sophisticated
> compiler could perform anti-inlining: recognizing a common code pattern,
> and replacing it wherever used with a call to a compiler-generated
> function definition. The fact that the common code was the result of a
> macro expansion would make it easier to recognize the feasibility of
> such an optimization. However, and it seems to me to be a harder
> optimization to perform than inlining, and I doubt that it is a common
> feature even of the most sophisticated compilers.

That kind of optimization would be the comp-sci equivalent of gilding
the lily.



Regards,

Uncle Steve

-- 
Should a professional politician be charged with molestation if he
kisses babies while attending political rallies?

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


#4536

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-05-23 01:04 +0100
Message-ID<0.dd74e92a138404c43559.20110523010437BST.874o4mnuy2.fsf@bsb.me.uk>
In reply to#4534
Uncle Steve <stevet810@gmail.com> writes:

> On Sun, May 22, 2011 at 1u1:18:36PM +0100, Ben Bacarisse wrote:
>> Uncle Steve <stevet810@gmail.com> writes:
>> 
>> > On Sun, May 22, 2011 at 02:49:51AM -0700, luser- -droog wrote:
>> >> 
>> >> I've been using integer offsets instead of pointers a lot lately and
>> >> I think you might be better off using the array formula explicitly:
>> >> 
>> >>  #define arena_obj_addr(x, n) ((void *) (x->arena + n * x->obj_size))
>> 
>> Everyone is taking chances here.  The x and n should be in parentheses
>> so that the macro expands as expected.  This is one reason why functions
>> are usually preferred.

I should also have said especially if the macro does not have an
ALL_CAPS name flagging it's macrosity.

> For a long time I've thought macros were preferable to functions for
> the reason that a function call has to save registers, stuff it's arguments on the
> stack, and so on.  Macros should just fold into the program text,

They should, but the onus is on the programmer to make that reasonable
(and where there are side effects in the expressions used in the macro
"call" this may not be possible). 

> but
> today inline functions are just as fast as macros.

Yes, using an inline function is better yet.  You seemed dead against
them which is why I commented on the macro.  Use a function and the
issue disappears.

>  It has become a
> matter of preference.  gcc even has the ability to use register
> calling conventions for function calls in some circumstances.  The
> distinction between a macro and a function call is becoming moot.

I don't see how you can say that.  The speed advantage that used to be
one of the main reasons to take the risk with macros has gone, but all
the potential bugs that function-like macros can hide are still there.

>> <snip>
>> > #define ARENA_TYPE	struct foo
>
>> > struct arena_s {
>> >    size_t        arena_size;
>> >    int           free_list;
>> >    size_t        free;
>> >    ARENA_TYPE *  arena;
>> > };
>> >
>> > And your access macro becomes:
>> >
>> > #define arena_obj_addr(x, n)   &x->arena[n]
>> 
>> Here the [n] is OK, but why risk it with x?  The (x) costs nothing and,
>> I think, saves time reading the macro since the reader does no have to
>> start worrying about what might be passed.
>
> No worries here.  I've edited for brevity in posting, but I always
> protect macro arguments from side-effects these days.  It doesn't look
> as clean and concise, which is why I omitted those statements from
> example code.  No biggie.

OK.  I'll try to remember to assume any errors in future code were added
for brevity and I'll save time by not commenting on it.

> In this newsgroup is it really preferable to see 
>
> #define arena_object_addr(x, n) ({	\
>    struct arena_s X = x;		\
>    int N = n;				\
>    *X->arena[N]; })			\
>
> for every dumb example that is posted?

The correct version of the macro is simpler than the one you seem to
think you'd write to make it safe.  Why would you write the above (it's
wrong, so it's obviously not what you really use) instead of

 *(x)->arena[n]

?  Also, why would you use a non-standard feature when it's not needed?  There
might be a reason to use ({...}) when a macro parameter is used more
than once that's not the case here.  I suppose if you know you'll never
use another compiler, tying code to language extensions is not a problem.

>  Possibly not if people can be
> reminded that all code posted in comp.lang.c is generally intended as
> an example.

One of the bug-bears of Usenet is "oh that's not the real code".  This
translates to "you've just wasted your time".  I'd vote for real code
(at the last code that's gone though a compiler) every time.

-- 
Ben.

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


#4545

FromUncle Steve <stevet810@gmail.com>
Date2011-05-23 02:36 -0400
Message-ID<ad38dbcccabfe98-406e6@gmail.com>
In reply to#4536
On Mon, May 23, 2011 at 01:04:37AM +0100, Ben Bacarisse wrote:
> Uncle Steve <stevet810@gmail.com> writes:
> 
> > On Sun, May 22, 2011 at 1u1:18:36PM +0100, Ben Bacarisse wrote:
> >> Uncle Steve <stevet810@gmail.com> writes:
> >> 
> >> > On Sun, May 22, 2011 at 02:49:51AM -0700, luser- -droog wrote:
> >> >> 
> >> >> I've been using integer offsets instead of pointers a lot lately and
> >> >> I think you might be better off using the array formula explicitly:
> >> >> 
> >> >>  #define arena_obj_addr(x, n) ((void *) (x->arena + n * x->obj_size))
> >> 
> >> Everyone is taking chances here.  The x and n should be in parentheses
> >> so that the macro expands as expected.  This is one reason why functions
> >> are usually preferred.
> 
> I should also have said especially if the macro does not have an
> ALL_CAPS name flagging it's macrosity.

But as some feel here, macrosity is a vanishing distinction.  I use
all-caps macro names for constant expressions and the like.  If I
think a macro will be more readable in lower-case, I'll do just that.
Shouted macro definitions interrupt the flow of source text when a
human is reading it, and I don't think I need that kind of distraction
in the code as much as some do.
 
> > For a long time I've thought macros were preferable to functions for
> > the reason that a function call has to save registers, stuff it's arguments on the
> > stack, and so on.  Macros should just fold into the program text,
> 
> They should, but the onus is on the programmer to make that reasonable
> (and where there are side effects in the expressions used in the macro
> "call" this may not be possible). 
> 
> > but
> > today inline functions are just as fast as macros.
> 
> Yes, using an inline function is better yet.  You seemed dead against
> them which is why I commented on the macro.  Use a function and the
> issue disappears.

I'm not "dead against" function calls for simple things.  I'm merely
predisposed against them.
 
> >  It has become a
> > matter of preference.  gcc even has the ability to use register
> > calling conventions for function calls in some circumstances.  The
> > distinction between a macro and a function call is becoming moot.
> 
> I don't see how you can say that.  The speed advantage that used to be
> one of the main reasons to take the risk with macros has gone, but all
> the potential bugs that function-like macros can hide are still there.

Sorry, I should say 'moot' in consideration of the now historic
performance advantage of macros over function calls.  In reality,
function calls /are/ slower than macro instances but the compiler
masks this when it inlines a function by omitting function preamble
and jinking the basic blocks of code to flow together as if they were
part of the immediate text.  

> >> <snip>
> >> > #define ARENA_TYPE	struct foo
> >
> >> > struct arena_s {
> >> >    size_t        arena_size;
> >> >    int           free_list;
> >> >    size_t        free;
> >> >    ARENA_TYPE *  arena;
> >> > };
> >> >
> >> > And your access macro becomes:
> >> >
> >> > #define arena_obj_addr(x, n)   &x->arena[n]
> >> 
> >> Here the [n] is OK, but why risk it with x?  The (x) costs nothing and,
> >> I think, saves time reading the macro since the reader does no have to
> >> start worrying about what might be passed.
> >
> > No worries here.  I've edited for brevity in posting, but I always
> > protect macro arguments from side-effects these days.  It doesn't look
> > as clean and concise, which is why I omitted those statements from
> > example code.  No biggie.
> 
> OK.  I'll try to remember to assume any errors in future code were added
> for brevity and I'll save time by not commenting on it.

Please do.  I find it's the cut-and-paste-modify step that introduces
errors into program code more so than writing it in the first place.
 
> > In this newsgroup is it really preferable to see 
> >
> > #define arena_object_addr(x, n) ({	\
> >    struct arena_s X = x;		\
> >    int N = n;				\
> >    *X->arena[N]; })			\
> >
> > for every dumb example that is posted?
> 
> The correct version of the macro is simpler than the one you seem to
> think you'd write to make it safe.  Why would you write the above (it's
> wrong, so it's obviously not what you really use) instead of
> 
>  *(x)->arena[n]

That's only correct if the macro is a simple one-liner.  If (x) is
used more than once and has side-effects, such as in (x++), you're
toast.
 
> ?  Also, why would you use a non-standard feature when it's not needed?  There
> might be a reason to use ({...}) when a macro parameter is used more
> than once that's not the case here.  I suppose if you know you'll never
> use another compiler, tying code to language extensions is not a problem.

I'm a creature of habit, I guess.  Note that while I didn't learn C
under gcc, it's about the only compiler I've used in the last
seventeen years.  Consequently, avoiding its extensions is not an
automatic process.  I'm making an effort to avoid non-portable code,
but it is slow going.
 
> >  Possibly not if people can be
> > reminded that all code posted in comp.lang.c is generally intended as
> > an example.
> 
> One of the bug-bears of Usenet is "oh that's not the real code".  This
> translates to "you've just wasted your time".  I'd vote for real code
> (at the last code that's gone though a compiler) every time.

I look at the majority of the example code posted in Usenet messages
as being contrived for the purposes of demonstration.  When I was a
total noob, comp.sources.unix and a few others were places where real
code was made available to Usenet readers.  So called real code is no
longer posted to newsgroups.  I'm not ecstatic that my contrived
examples are not perfect, but the alternative is to post my 'real
code' and annoy people who would prefer the exemplar pared down to the
bare minimum.

The arena allocator I've been on about is instantiated as a .h file
and is over 500 lines of code at this time.  It carries with it all
the 'baggage' of my development environment and would make the
discussion of its data structures and algorithm very awkward.  A
reasonable compromise would be to ensure that posted code compiles
and works as expected, but even than that won't correct for all
possible errors:  note that I buggered up the for() loop in the
arena_creat() function without triggering the error during testing.

I'll endeavor to post better code in subsequent messages, but it is
not always practical to test quick one-off constructs completely when
so many things compete for my (and your) time.  I suppose I might
sound more intelligent and authoritative if my messages never
contained errors, but then I might never post at all if that were a
basic prerequisite for Usenet participation.  Somewhere there is a
happy medium that will satisfy everyone here.  I'll look more closely
for it. :)



Regards,

Uncle Steve

-- 
Should a professional politician be charged with molestation if he
kisses babies while attending political rallies?

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


#4555

Fromluser- -droog <mijoryx@yahoo.com>
Date2011-05-23 00:39 -0700
Message-ID<114c5ef1-0994-4946-bc01-7616bda5bb87@l26g2000yqm.googlegroups.com>
In reply to#4545
On May 23, 1:36 am, Uncle Steve <stevet...@gmail.com> wrote:
> On Mon, May 23, 2011 at 01:04:37AM +0100, Ben Bacarisse wrote:
>
> > One of the bug-bears of Usenet is "oh that's not the real code".  This
> > translates to "you've just wasted your time".  I'd vote for real code
> > (at the last code that's gone though a compiler) every time.
>
> I look at the majority of the example code posted in Usenet messages
> as being contrived for the purposes of demonstration.  When I was a
> total noob, comp.sources.unix and a few others were places where real
> code was made available to Usenet readers.  So called real code is no
> longer posted to newsgroups.  I'm not ecstatic that my contrived
> examples are not perfect, but the alternative is to post my 'real
> code' and annoy people who would prefer the exemplar pared down to the
> bare minimum.
>

Cast my vote for real code. Unless you're telling a story with little
pieces
of code. That's good too.

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


#4561

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-05-23 14:44 +0100
Message-ID<0.b19c2eb4ac372a8142d2.20110523144418BST.87fwo5fs5p.fsf@bsb.me.uk>
In reply to#4545
Uncle Steve <stevet810@gmail.com> writes:

> On Mon, May 23, 2011 at 01:04:37AM +0100, Ben Bacarisse wrote:
>> Uncle Steve <stevet810@gmail.com> writes:
>> 
>> > On Sun, May 22, 2011 at 1u1:18:36PM +0100, Ben Bacarisse wrote:
>> >> Uncle Steve <stevet810@gmail.com> writes:
>> >> 
>> >> > On Sun, May 22, 2011 at 02:49:51AM -0700, luser- -droog wrote:
>> >> >> 
>> >> >> I've been using integer offsets instead of pointers a lot lately and
>> >> >> I think you might be better off using the array formula explicitly:
>> >> >> 
>> >> >>  #define arena_obj_addr(x, n) ((void *) (x->arena + n * x->obj_size))
>> >> 
>> >> Everyone is taking chances here.  The x and n should be in parentheses
>> >> so that the macro expands as expected.  This is one reason why functions
>> >> are usually preferred.
>> 
>> I should also have said especially if the macro does not have an
>> ALL_CAPS name flagging it's macrosity.
>
> But as some feel here, macrosity is a vanishing distinction.

There you go again.  I won't say why not another time.  Ian's also said
why the distinction is changing bit certainly not vanishing.  Presumably
you don't accept the arguments, presumably because you never make a
mistake with your macros.  Sorry, I just spotted "some".  Who?  You seem
to suggest you don't hold this view anymore.

>  I use
> all-caps macro names for constant expressions and the like.  If I
> think a macro will be more readable in lower-case, I'll do just that.
> Shouted macro definitions interrupt the flow of source text when a
> human is reading it, and I don't think I need that kind of distraction
> in the code as much as some do.

Ah.  You code is for your eye only.  Not only should it not be commented
on because you've edited for brevity, it should not be commented on for
readability or clarity because only you'll read it.  I get it.  Nothing
in you posted code should be commented on.

>> > For a long time I've thought macros were preferable to functions for
>> > the reason that a function call has to save registers, stuff it's arguments on the
>> > stack, and so on.  Macros should just fold into the program text,
>> 
>> They should, but the onus is on the programmer to make that reasonable
>> (and where there are side effects in the expressions used in the macro
>> "call" this may not be possible). 
>> 
>> > but
>> > today inline functions are just as fast as macros.
>> 
>> Yes, using an inline function is better yet.  You seemed dead against
>> them which is why I commented on the macro.  Use a function and the
>> issue disappears.
>
> I'm not "dead against" function calls for simple things.  I'm merely
> predisposed against them.

It no longer matters.  Your code is for your eyes only and it does not
have any of the errors that plague other people when they use macros.
Any evidence to the contrary here is due to your thought posting code
edited versions for brevity.

>> >  It has become a
>> > matter of preference.  gcc even has the ability to use register
>> > calling conventions for function calls in some circumstances.  The
>> > distinction between a macro and a function call is becoming moot.
>> 
>> I don't see how you can say that.  The speed advantage that used to be
>> one of the main reasons to take the risk with macros has gone, but all
>> the potential bugs that function-like macros can hide are still there.
>
> Sorry, I should say 'moot' in consideration of the now historic
> performance advantage of macros over function calls.  In reality,
> function calls /are/ slower than macro instances but the compiler
> masks this when it inlines a function by omitting function preamble
> and jinking the basic blocks of code to flow together as if they were
> part of the immediate text.  

I am very happy to have the slowness of something "masked" by the
compiler making if fast.  In fact, I'd go so far as to say that it's not
slow anymore but you that's just my way of looking at it.

>> >> <snip>
>> >> > #define ARENA_TYPE	struct foo
>> >
>> >> > struct arena_s {
>> >> >    size_t        arena_size;
>> >> >    int           free_list;
>> >> >    size_t        free;
>> >> >    ARENA_TYPE *  arena;
>> >> > };
>> >> >
>> >> > And your access macro becomes:
>> >> >
>> >> > #define arena_obj_addr(x, n)   &x->arena[n]
>> >> 
>> >> Here the [n] is OK, but why risk it with x?  The (x) costs nothing and,
>> >> I think, saves time reading the macro since the reader does no have to
>> >> start worrying about what might be passed.
>> >
>> > No worries here.  I've edited for brevity in posting, but I always
>> > protect macro arguments from side-effects these days.  It doesn't look
>> > as clean and concise, which is why I omitted those statements from
>> > example code.  No biggie.
>> 
>> OK.  I'll try to remember to assume any errors in future code were added
>> for brevity and I'll save time by not commenting on it.
>
> Please do.  I find it's the cut-and-paste-modify step that introduces
> errors into program code more so than writing it in the first place.
>  
>> > In this newsgroup is it really preferable to see 
>> >
>> > #define arena_object_addr(x, n) ({	\
>> >    struct arena_s X = x;		\
>> >    int N = n;				\
>> >    *X->arena[N]; })			\
>> >
>> > for every dumb example that is posted?
>> 
>> The correct version of the macro is simpler than the one you seem to
>> think you'd write to make it safe.  Why would you write the above (it's
>> wrong, so it's obviously not what you really use) instead of
>> 
>>  *(x)->arena[n]
>
> That's only correct if the macro is a simple one-liner.  If (x) is
> used more than once and has side-effects, such as in (x++), you're
> toast.

You posted an incorrect one-liner.  You then said it's OK because you
really use 4 lines and an non-C construct to do these things.  The seems
daft to me.  If the code is short (and this code was short) just write
the short version correctly.  Errors happen, so more lines are often
worse than fewer.  I know, errors don't happen in your real code so you
can be as verbose as you like, but for other people reading this shorter
macros are almost always better.

>> ?  Also, why would you use a non-standard feature when it's not needed?  There
>> might be a reason to use ({...}) when a macro parameter is used more
>> than once that's not the case here.  I suppose if you know you'll never
>> use another compiler, tying code to language extensions is not a problem.
>
> I'm a creature of habit, I guess.  Note that while I didn't learn C
> under gcc, it's about the only compiler I've used in the last
> seventeen years.  Consequently, avoiding its extensions is not an
> automatic process.  I'm making an effort to avoid non-portable code,
> but it is slow going.

gcc -std=c99 -pedantic if you want to avoid extensions.  gcc -ansi
-pedantic is you want to avoid more non-portable features.  I am sure
you know this, and using it in your real builds, but I comment in case
anyone else could use a reminder of how to make gcc limit itself to
standard C.

>> >  Possibly not if people can be
>> > reminded that all code posted in comp.lang.c is generally intended as
>> > an example.
>> 
>> One of the bug-bears of Usenet is "oh that's not the real code".  This
>> translates to "you've just wasted your time".  I'd vote for real code
>> (at the last code that's gone though a compiler) every time.
>
> I look at the majority of the example code posted in Usenet messages
> as being contrived for the purposes of demonstration.

Maybe, but it's real code in the sense that people want comments on it.

>  When I was a
> total noob, comp.sources.unix and a few others were places where real
> code was made available to Usenet readers.  So called real code is no
> longer posted to newsgroups.  I'm not ecstatic that my contrived
> examples are not perfect, but the alternative is to post my 'real
> code' and annoy people who would prefer the exemplar pared down to the
> bare minimum.

Maybe just prefix the posting with "This is not real code.  If there
are mistakes they are probably not there in the original so don't spend
time on the details.  Stick to the gist of it."

> The arena allocator I've been on about is instantiated as a .h file
> and is over 500 lines of code at this time.

Hmmm.... I wonder if that affects the performance.  Maybe not.

>  It carries with it all
> the 'baggage' of my development environment and would make the
> discussion of its data structures and algorithm very awkward.  A
> reasonable compromise would be to ensure that posted code compiles
> and works as expected, but even than that won't correct for all
> possible errors:  note that I buggered up the for() loop in the
> arena_creat() function without triggering the error during testing.
>
> I'll endeavor to post better code in subsequent messages, but it is
> not always practical to test quick one-off constructs completely when
> so many things compete for my (and your) time.  I suppose I might
> sound more intelligent and authoritative if my messages never
> contained errors, but then I might never post at all if that were a
> basic prerequisite for Usenet participation.  Somewhere there is a
> happy medium that will satisfy everyone here.  I'll look more closely
> for it. :)

Don't worry to much about it.  No one else seems to mind, and I've got a
solution that works for me.

-- 
Ben.

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


#4563

FromSeebs <usenet-nospam@seebs.net>
Date2011-05-23 15:16 +0000
Message-ID<slrnitku20.544.usenet-nospam@guild.seebs.net>
In reply to#4561
On 2011-05-23, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
> I am very happy to have the slowness of something "masked" by the
> compiler making if fast.

Beautiful phrasing.

I think this gets to the heart of why good programmers measure before they
optimize; our guesses as to what's fast and what's slow are often useless.
I spent a while trying to improve the performance of the computational
inner loop of a program, then thought to benchmark it a bit.  It turns
out the "computational inner loop" was under 10% of the run time*.

... oops.

-s
[*] Did you know that rendering antialiased lines on a 32-bit display is
actually more computationally expensive than calculating their end points?
Apparently, I didn't.
-- 
Copyright 2011, all wrongs reversed.  Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

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


#4565

FromUncle Steve <stevet810@gmail.com>
Date2011-05-23 11:41 -0400
Message-ID<9a60f6fc5b1439a-7a342@gmail.com>
In reply to#4561
On Mon, May 23, 2011 at 02:44:18PM +0100, Ben Bacarisse wrote:
> Uncle Steve <stevet810@gmail.com> writes:
> 
> > On Mon, May 23, 2011 at 01:04:37AM +0100, Ben Bacarisse wrote:
> >> Uncle Steve <stevet810@gmail.com> writes:
> >> 
> >> > On Sun, May 22, 2011 at 1u1:18:36PM +0100, Ben Bacarisse wrote:
> >> >> Uncle Steve <stevet810@gmail.com> writes:
> >> >> 
> >> >> > On Sun, May 22, 2011 at 02:49:51AM -0700, luser- -droog wrote:
> >> >> >> 
> >> >> >> I've been using integer offsets instead of pointers a lot lately and
> >> >> >> I think you might be better off using the array formula explicitly:
> >> >> >> 
> >> >> >>  #define arena_obj_addr(x, n) ((void *) (x->arena + n * x->obj_size))
> >> >> 
> >> >> Everyone is taking chances here.  The x and n should be in parentheses
> >> >> so that the macro expands as expected.  This is one reason why functions
> >> >> are usually preferred.
> >> 
> >> I should also have said especially if the macro does not have an
> >> ALL_CAPS name flagging it's macrosity.
> >
> > But as some feel here, macrosity is a vanishing distinction.
> 
> There you go again.  I won't say why not another time.  Ian's also said
> why the distinction is changing bit certainly not vanishing.  Presumably
> you don't accept the arguments, presumably because you never make a
> mistake with your macros.  Sorry, I just spotted "some".  Who?  You seem
> to suggest you don't hold this view anymore.

Look.  There are coding idioms that I use habitually; macros figure
prominently in specific roles.  That's my coding standard, FWIW, and
as I've no supervisor dictating some other arbitrary standard, I am
perfectly happy with my style more or less as-is.  My brain is not
composed of granite, so I am free to change my coding standards at
any time if I see a need to do so.
 
> >  I use
> > all-caps macro names for constant expressions and the like.  If I
> > think a macro will be more readable in lower-case, I'll do just that.
> > Shouted macro definitions interrupt the flow of source text when a
> > human is reading it, and I don't think I need that kind of distraction
> > in the code as much as some do.
> 
> Ah.  You code is for your eye only.  Not only should it not be commented
> on because you've edited for brevity, it should not be commented on for
> readability or clarity because only you'll read it.  I get it.  Nothing
> in you posted code should be commented on.

See below.
 
> >> > For a long time I've thought macros were preferable to functions for
> >> > the reason that a function call has to save registers, stuff it's arguments on the
> >> > stack, and so on.  Macros should just fold into the program text,
> >> 
> >> They should, but the onus is on the programmer to make that reasonable
> >> (and where there are side effects in the expressions used in the macro
> >> "call" this may not be possible). 
> >> 
> >> > but
> >> > today inline functions are just as fast as macros.
> >> 
> >> Yes, using an inline function is better yet.  You seemed dead against
> >> them which is why I commented on the macro.  Use a function and the
> >> issue disappears.
> >
> > I'm not "dead against" function calls for simple things.  I'm merely
> > predisposed against them.
> 
> It no longer matters.  Your code is for your eyes only and it does not
> have any of the errors that plague other people when they use macros.
> Any evidence to the contrary here is due to your thought posting code
> edited versions for brevity.

...
 
> >> >  It has become a
> >> > matter of preference.  gcc even has the ability to use register
> >> > calling conventions for function calls in some circumstances.  The
> >> > distinction between a macro and a function call is becoming moot.
> >> 
> >> I don't see how you can say that.  The speed advantage that used to be
> >> one of the main reasons to take the risk with macros has gone, but all
> >> the potential bugs that function-like macros can hide are still there.
> >
> > Sorry, I should say 'moot' in consideration of the now historic
> > performance advantage of macros over function calls.  In reality,
> > function calls /are/ slower than macro instances but the compiler
> > masks this when it inlines a function by omitting function preamble
> > and jinking the basic blocks of code to flow together as if they were
> > part of the immediate text.  
> 
> I am very happy to have the slowness of something "masked" by the
> compiler making if fast.  In fact, I'd go so far as to say that it's not
> slow anymore but you that's just my way of looking at it.

Right.

> >> >> <snip>
> >> >> > #define ARENA_TYPE	struct foo
> >> >
> >> >> > struct arena_s {
> >> >> >    size_t        arena_size;
> >> >> >    int           free_list;
> >> >> >    size_t        free;
> >> >> >    ARENA_TYPE *  arena;
> >> >> > };
> >> >> >
> >> >> > And your access macro becomes:
> >> >> >
> >> >> > #define arena_obj_addr(x, n)   &x->arena[n]
> >> >> 
> >> >> Here the [n] is OK, but why risk it with x?  The (x) costs nothing and,
> >> >> I think, saves time reading the macro since the reader does no have to
> >> >> start worrying about what might be passed.
> >> >
> >> > No worries here.  I've edited for brevity in posting, but I always
> >> > protect macro arguments from side-effects these days.  It doesn't look
> >> > as clean and concise, which is why I omitted those statements from
> >> > example code.  No biggie.
> >> 
> >> OK.  I'll try to remember to assume any errors in future code were added
> >> for brevity and I'll save time by not commenting on it.
> >
> > Please do.  I find it's the cut-and-paste-modify step that introduces
> > errors into program code more so than writing it in the first place.
> >  
> >> > In this newsgroup is it really preferable to see 
> >> >
> >> > #define arena_object_addr(x, n) ({	\
> >> >    struct arena_s X = x;		\
> >> >    int N = n;				\
> >> >    *X->arena[N]; })			\
> >> >
> >> > for every dumb example that is posted?
> >> 
> >> The correct version of the macro is simpler than the one you seem to
> >> think you'd write to make it safe.  Why would you write the above (it's
> >> wrong, so it's obviously not what you really use) instead of
> >> 
> >>  *(x)->arena[n]
> >
> > That's only correct if the macro is a simple one-liner.  If (x) is
> > used more than once and has side-effects, such as in (x++), you're
> > toast.
> 
> You posted an incorrect one-liner.  You then said it's OK because you
> really use 4 lines and an non-C construct to do these things.  The seems
> daft to me.  If the code is short (and this code was short) just write
> the short version correctly.  Errors happen, so more lines are often
> worse than fewer.  I know, errors don't happen in your real code so you
> can be as verbose as you like, but for other people reading this shorter
> macros are almost always better.

I didn't say it was ok that I made an error; I merely explained the
cause.  Then you jumped on me for using a gccism.  I've already spent
about four hours in the last twenty-four writing messages to this
newsgroup.  How slowly should I write to Usenet?
 
> >> ?  Also, why would you use a non-standard feature when it's not needed?  There
> >> might be a reason to use ({...}) when a macro parameter is used more
> >> than once that's not the case here.  I suppose if you know you'll never
> >> use another compiler, tying code to language extensions is not a problem.
> >
> > I'm a creature of habit, I guess.  Note that while I didn't learn C
> > under gcc, it's about the only compiler I've used in the last
> > seventeen years.  Consequently, avoiding its extensions is not an
> > automatic process.  I'm making an effort to avoid non-portable code,
> > but it is slow going.
> 
> gcc -std=c99 -pedantic if you want to avoid extensions.  gcc -ansi
> -pedantic is you want to avoid more non-portable features.  I am sure
> you know this, and using it in your real builds, but I comment in case
> anyone else could use a reminder of how to make gcc limit itself to
> standard C.

Actually, I'm not using that for my 'real' builds since I'm hardly
building anything at all right now.  Instead I am writing and
designing.  Trust me, I have enough details up in the air right now.
I don't even care if my code is compilable right at this moment as
designing it properly is a higher priority.  If I had learned standard
C previously instead of gcc C, I wouldn't have this problem.  So at
some point when the code base is stable, /then/ (and only then) will
I go through it to remove gccisms in the older stuff. 

> >> >  Possibly not if people can be
> >> > reminded that all code posted in comp.lang.c is generally intended as
> >> > an example.
> >> 
> >> One of the bug-bears of Usenet is "oh that's not the real code".  This
> >> translates to "you've just wasted your time".  I'd vote for real code
> >> (at the last code that's gone though a compiler) every time.
> >
> > I look at the majority of the example code posted in Usenet messages
> > as being contrived for the purposes of demonstration.
> 
> Maybe, but it's real code in the sense that people want comments on it.

True enough, but that also implies that people are doing just as I am,
and shortening their code to make their queries and examples more
concise.
 
> >  When I was a
> > total noob, comp.sources.unix and a few others were places where real
> > code was made available to Usenet readers.  So called real code is no
> > longer posted to newsgroups.  I'm not ecstatic that my contrived
> > examples are not perfect, but the alternative is to post my 'real
> > code' and annoy people who would prefer the exemplar pared down to the
> > bare minimum.
> 
> Maybe just prefix the posting with "This is not real code.  If there
> are mistakes they are probably not there in the original so don't spend
> time on the details.  Stick to the gist of it."
> 
> > The arena allocator I've been on about is instantiated as a .h file
> > and is over 500 lines of code at this time.
> 
> Hmmm.... I wonder if that affects the performance.  Maybe not.

Quite a bit of it is documentation.
 
> >  It carries with it all
> > the 'baggage' of my development environment and would make the
> > discussion of its data structures and algorithm very awkward.  A
> > reasonable compromise would be to ensure that posted code compiles
> > and works as expected, but even than that won't correct for all
> > possible errors:  note that I buggered up the for() loop in the
> > arena_creat() function without triggering the error during testing.
> >
> > I'll endeavor to post better code in subsequent messages, but it is
> > not always practical to test quick one-off constructs completely when
> > so many things compete for my (and your) time.  I suppose I might
> > sound more intelligent and authoritative if my messages never
> > contained errors, but then I might never post at all if that were a
> > basic prerequisite for Usenet participation.  Somewhere there is a
> > happy medium that will satisfy everyone here.  I'll look more closely
> > for it. :)
> 
> Don't worry to much about it.  No one else seems to mind, and I've got a
> solution that works for me.

Ok, I won't.



Regards,

Uncle Steve

-- 
Should a professional politician be charged with molestation if he
kisses babies while attending political rallies?

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


#5234

FromDavid Thompson <dave.thompson2@verizon.net>
Date2011-06-01 16:33 -0400
Message-ID<rt7du61rok03gsn7nmhik9hh3rh0edn5g8@4ax.com>
In reply to#4561
On Mon, 23 May 2011 14:44:18 +0100, Ben Bacarisse
<ben.usenet@bsb.me.uk> wrote:
<snip: using GCCisms>
> gcc -std=c99 -pedantic if you want to avoid extensions.  gcc -ansi
> -pedantic is you want to avoid more non-portable features.  <snip>

Other than those using (implementation-reserved) double-underscore,
which are easy enough to search for (unless you construct them with
token-pasting, and if so you deserve whatever problems you get).

And things which are implementation-dependent (unspec or impl-def) in
the standard. Those can be nonportable in general, but not from gcc
specifically, and gcc doesn't flag them as such. (In some cases, the
impl-dependent range or signedness of a type may trigger value-range,
conversion-range, or unsigned-comparison warnings.)

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


#4395

FromUncle Steve <stevet810@gmail.com>
Date2011-05-19 18:34 -0400
Message-ID<fb81382c91724d0-17e8d@gmail.com>
In reply to#4275
On Thu, May 19, 2011 at 03:22:18AM +0100, Ben Bacarisse wrote:
[snip]


Ok, here's a quick and dirty hack that measures a highly contrived
scenario.  This code first allocates two arenas of different size, and
then ping-pongs the allocations between the two arenas for a defined
number of iterations.  Then, I do more or less the same thing with
malloc.y

The preliminary results show that my special-purpose allocator is 2-3
times faster than glibc malloc.  Not quite and order-of-magnitude
difference in performance (unless you think in base-2), but very
acceptable.  In some programs there may be a larger difference in
performance becuase of reduceed memory fragmentation or reduced
overall memory use.  I do not plan to isolate those factors at this
time to measure their effect.

Code is compiled with "gcc -O0 -o arena_test arena_test.c -lrt"

The test platform here is an Intel Atom netbook running at 1.333GHz,
1G RAM, OpenSuSE 11.4, libc-2.11.3, gcc 4.5.1 20101208.

Typical result:

[31/22:32] nb:pts/10 stevet ~/stuff/src/libs/tools/test: ./arena_test 
Arena: Iterations: 100000; elapsed CPU time (msec): 39181
Malloc:  Iterations: 100000; elapsed CPU time (msec): 107265


Code follows:

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>


#define TEST_SIZE    1024 * 1024
#define ITERATIONS   100000

#define DIFFERENCE   5


struct arena_head_s {
   int      obj_size;
   int      arena_size;
   unsigned char *
            arena;
   int      free;
   int      free_list;
};

typedef struct arena_head_s arena_head;


#define arena_obj_addr(x, n) ((void *) &x->arena[n * x->obj_size])


arena_qa(arena_head *x)
{
   int n;

   n = x->free_list;

   if(n != -1) {
      x->free_list = *((int *) arena_obj_addr(x, n));
      x->free--;
   }

   return(n);
}   

void arena_free(arena_head *p, int n)
{
   *((int *) arena_obj_addr(p, n)) = p->free_list;
   p->free_list = n;
   p->free++;

   return;
}

arena_head * arena_creat(size_t s, int n)
{
   arena_head * h;
   int i;

   h = malloc(sizeof(arena_head));
   if(h == NULL) {
      perror("malloc()");
      exit(1);
   }

   h->obj_size = s;
   h->arena_size = n;
   h->free = n;

   h->arena = malloc(s * n);
   if(h->arena == NULL) {
      perror("malloc()");
      exit(1);
   }

   h->free_list = 0;

   for(i = 0; i < n; i++)
      *((int *) arena_obj_addr(h, i)) = i + 1;

   *((int *) arena_obj_addr(h, i)) = -1;

   return(h);
}


typedef unsigned long long int T64;

#define processcputime(p)                                                   \
{                                                                           \
        T64     *       t = p;                                              \
        struct timespec T;                                                  \
                                                                            \
        if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &T) == -1)   {          \
                perror("clock_gettime()");                                  \
               exit(1);                                                     \
        }                                                                   \
                                                                            \
        *t = ((T64)T.tv_sec) * 1000000LL + ((T64) T.tv_nsec / 1000);        \
}


struct test_load_s {
   int   ref;
   int   data;
};

typedef struct test_load_s test_load;


void work(test_load *p)
{
   if(!p) {
      perror("null ptr");
      exit(1);
   }
      
   p->ref++;
   p->data = (int) p % 4 * rand();

   return;
}



int   main(int argc, char ** argv)
{
   arena_head *h1, *h2;
   T64 start, end;
   int i, n;
   test_load *p;


   processcputime(&start);

   h1 = arena_creat(sizeof(test_load), TEST_SIZE);
   h2 = arena_creat(sizeof(test_load) + DIFFERENCE, TEST_SIZE);

   if(!h1 || !h2) {
      perror("arenas");
      exit(1);
   }

   processcputime(&start);

   for(i = 0; i < ITERATIONS; i++) {
      n = arena_qa(h1);
      if(n == -1) {
         perror("Ooops.");
         exit(1);
      }
      work(arena_obj_addr(h1, n));

      n = arena_qa(h2);
      if(n == -1) {
         perror("Ooops 2.");
         exit(1);
      }
      work(arena_obj_addr(h2, n));
   }

   processcputime(&end);

   fprintf(stdout, "Arena: Iterations: %ld; elapsed CPU time (msec): %ld\n", ITERATIONS, (end - start));

   processcputime(&start);

   for(i = 0; i < ITERATIONS; i++) {
      p = malloc(sizeof(test_load));
      if(!p) {
         perror("malloc()");
         exit(1);
      }
      work(p);

      p = malloc(sizeof(test_load) + DIFFERENCE);
      if(!p) {
         perror("malloc2()");
         exit(1);
      }
      work(p);
   }
           
   processcputime(&end);

   fprintf(stdout, "Malloc:  Iterations: %ld; elapsed CPU time (msec): %ld\n", ITERATIONS, (end - start));

   exit(0);
}




Regards,

Uncle Steve

-- 
Should a professional politician be charged with molestation if he
kisses babies while attending political rallies?

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


#4406

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-05-20 02:36 +0100
Message-ID<0.59d068d4aa2044bdca20.20110520023648BST.87ei3uqhjj.fsf@bsb.me.uk>
In reply to#4395
Uncle Steve <stevet810@gmail.com> writes:

> On Thu, May 19, 2011 at 03:22:18AM +0100, Ben Bacarisse wrote:
> [snip]
>
>
> Ok, here's a quick and dirty hack that measures a highly contrived
> scenario.  This code first allocates two arenas of different size, and
> then ping-pongs the allocations between the two arenas for a defined
> number of iterations.  Then, I do more or less the same thing with
> malloc.y
>
> The preliminary results show that my special-purpose allocator is 2-3
> times faster than glibc malloc.  Not quite and order-of-magnitude
> difference in performance (unless you think in base-2), but very
> acceptable.  In some programs there may be a larger difference in
> performance becuase of reduceed memory fragmentation or reduced
> overall memory use.  I do not plan to isolate those factors at this
> time to measure their effect.

You don't include the set-up time for the areans.  That's fair if the
pattern you expect to see is a very large number of allocations and a
lot of re-use.  If, however, new areans are needed in a long running
program (because not all the memory is re-used) you'd have to include
this cost.

It makes a huge difference with the numbers you've picked: it halves the
benefit on my system (3x vs 1.5x speed).  I can reduce the effect of
course just by increasing the number of timed iterations.  For very
small objects, with lots of optimisation and excluding the start-up
costs I can get just over your order of magnitude speedup.  That's a
rather contrived scenario though.  In particular, it is likely that the
allocation code will not be able to be inlined (as I think it can be
here).

Thank you for providing something that can give real data, albeit for
rather specific situations.  FWIW I am on using an Intel(R) Core(TM)2
Duo CPU P8700 @ 2.53GHz.

If I have time (looks unlikely) I'll plug it into a small binary tree
program to see what happens when there is a little work being done too.

<snip code>
-- 
Ben.

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


#4436

FromUncle Steve <stevet810@gmail.com>
Date2011-05-20 12:26 -0400
Message-ID<a8a6d14a9ed9b70-0c8ce@gmail.com>
In reply to#4406
On Fri, May 20, 2011 at 02:36:48AM +0100, Ben Bacarisse wrote:
> Uncle Steve <stevet810@gmail.com> writes:
> 
> > On Thu, May 19, 2011 at 03:22:18AM +0100, Ben Bacarisse wrote:
> > [snip]
> >
> >
> > Ok, here's a quick and dirty hack that measures a highly contrived
> > scenario.  This code first allocates two arenas of different size, and
> > then ping-pongs the allocations between the two arenas for a defined
> > number of iterations.  Then, I do more or less the same thing with
> > malloc.y
> >
> > The preliminary results show that my special-purpose allocator is 2-3
> > times faster than glibc malloc.  Not quite and order-of-magnitude
> > difference in performance (unless you think in base-2), but very
> > acceptable.  In some programs there may be a larger difference in
> > performance becuase of reduceed memory fragmentation or reduced
> > overall memory use.  I do not plan to isolate those factors at this
> > time to measure their effect.
> 
> You don't include the set-up time for the areans.  That's fair if the
> pattern you expect to see is a very large number of allocations and a
> lot of re-use.  If, however, new areans are needed in a long running
> program (because not all the memory is re-used) you'd have to include
> this cost.

True enough, but it's not wrong to charge the set-up cost to program
initialization mainly because the arena allocator is mainly suitable
for those situations where there will be a lot of re-use.  Malloc
may also have set-up costs as well that are hidden in program
initialization, but that will depend on the implementation.
 
> It makes a huge difference with the numbers you've picked: it halves the
> benefit on my system (3x vs 1.5x speed).  I can reduce the effect of
> course just by increasing the number of timed iterations.  For very
> small objects, with lots of optimisation and excluding the start-up
> costs I can get just over your order of magnitude speedup.  That's a
> rather contrived scenario though.  In particular, it is likely that the
> allocation code will not be able to be inlined (as I think it can be
> here).

Whether or not the code is inlined is going to depend more on whether
you are interested in performance or code size.  Of course it is
trivial to force the allocation routine inline -- just make it a
macro.  Whether that makes any sort of difference at all is highly
application specific, and is bound to be of less importance than the
difference in algorithm design.
 
> Thank you for providing something that can give real data, albeit for
> rather specific situations.  FWIW I am on using an Intel(R) Core(TM)2
> Duo CPU P8700 @ 2.53GHz.

I'm mildly curious as to the numbers you got, would you mind posting
them?

> If I have time (looks unlikely) I'll plug it into a small binary tree
> program to see what happens when there is a little work being done too.

Coincidentally, a binary tree algorithm is just the application that I
envisioned as suitable for use with this allocator.  At some point I
probably will be measuring its performance, so I'll have a better idea
of whats going on in that case when I get to it.



Regards,

Uncle Steve

-- 
Should a professional politician be charged with molestation if he
kisses babies while attending political rallies?

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


#4464

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-05-20 23:32 +0100
Message-ID<0.0445c33066fc3df6c97c.20110520233246BST.87ei3tove9.fsf@bsb.me.uk>
In reply to#4436
Uncle Steve <stevet810@gmail.com> writes:

<snip>
> I'm mildly curious as to the numbers you got, would you mind posting
> them?

Not at all.  Exactly as per your compile but I added more iterations
just in case I was not getting good times:

Arena: Iterations: 1000000; elapsed CPU time (msec): 36109
Malloc:  Iterations: 1000000; elapsed CPU time (msec): 107952

If I add in the set-up costs:

Arena: Iterations: 1000000; elapsed CPU time (msec): 70330
Malloc:  Iterations: 1000000; elapsed CPU time (msec): 107935

Base case again but with maximum optimisation turned on (-O3):

Arena: Iterations: 1000000; elapsed CPU time (msec): 12303
Malloc:  Iterations: 1000000; elapsed CPU time (msec): 104033

and the same but, again, with the set-up time included:

Arena: Iterations: 1000000; elapsed CPU time (msec): 39187
Malloc:  Iterations: 1000000; elapsed CPU time (msec): 102874

(gcc version 4.4.3)

<snip>
-- 
Ben.

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


#4479

FromUncle Steve <stevet810@gmail.com>
Date2011-05-20 21:17 -0400
Message-ID<674e95901d3dba6-6851e@gmail.com>
In reply to#4464
On Fri, May 20, 2011 at 11:32:46PM +0100, Ben Bacarisse wrote:
> Uncle Steve <stevet810@gmail.com> writes:
> 
> <snip>
> > I'm mildly curious as to the numbers you got, would you mind posting
> > them?
> 
> Not at all.  Exactly as per your compile but I added more iterations
> just in case I was not getting good times:
> 
> Arena: Iterations: 1000000; elapsed CPU time (msec): 36109
> Malloc:  Iterations: 1000000; elapsed CPU time (msec): 107952
> 
> If I add in the set-up costs:
> 
> Arena: Iterations: 1000000; elapsed CPU time (msec): 70330
> Malloc:  Iterations: 1000000; elapsed CPU time (msec): 107935
> 
> Base case again but with maximum optimisation turned on (-O3):
> 
> Arena: Iterations: 1000000; elapsed CPU time (msec): 12303
> Malloc:  Iterations: 1000000; elapsed CPU time (msec): 104033
> 
> and the same but, again, with the set-up time included:
> 
> Arena: Iterations: 1000000; elapsed CPU time (msec): 39187
> Malloc:  Iterations: 1000000; elapsed CPU time (msec): 102874

Funny.  Your numbers are almost exactly 10x better than mine on the
netbook.  But at -O3, I get: 

Arena: Iterations: 100000; elapsed CPU time (msec): 28540
Malloc:  Iterations: 100000; elapsed CPU time (msec): 97913

Which is 2.5 (*10) poorer than your results.  I don't know what that
actually signifies, but it's kind of interesting.



Regards,

Uncle Steve

-- 
Should a professional politician be charged with molestation if he
kisses babies while attending political rallies?

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


#4484

FromIan Collins <ian-news@hotmail.com>
Date2011-05-21 14:30 +1200
Message-ID<93omefF1bbU15@mid.individual.net>
In reply to#4395
On 05/20/11 10:34 AM, Uncle Steve wrote:

A couple of comments on the code:

<snip>

> arena_head * arena_creat(size_t s, int n)
> {
>     arena_head * h;
>     int i;
>
>     h = malloc(sizeof(arena_head));
>     if(h == NULL) {
>        perror("malloc()");
>        exit(1);
>     }
>
>     h->obj_size = s;
>     h->arena_size = n;
>     h->free = n;
>
>     h->arena = malloc(s * n);
>     if(h->arena == NULL) {
>        perror("malloc()");
>        exit(1);
>     }
>
>     h->free_list = 0;
>
>     for(i = 0; i<  n; i++)
>        *((int *) arena_obj_addr(h, i)) = i + 1;
>
>     *((int *) arena_obj_addr(h, i)) = -1;

This writes past the end of the allocated block.

>     return(h);
> }
>
>
> typedef unsigned long long int T64;
>
> #define processcputime(p)                                                   \

Why go the the trouble of declaring this as a messy macro?

-- 
Ian Collins

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


#4494

FromUncle Steve <stevet810@gmail.com>
Date2011-05-21 11:13 -0400
Message-ID<b5cf4d9e084fa3f-1edbb@gmail.com>
In reply to#4484
On Sat, May 21, 2011 at 02:30:39PM +1200, Ian Collins wrote:
> On 05/20/11 10:34 AM, Uncle Steve wrote:
> 
> A couple of comments on the code:
> 
> <snip>
> 
> >arena_head * arena_creat(size_t s, int n)
> >{
> >    arena_head * h;
> >    int i;
> >
> >    h = malloc(sizeof(arena_head));
> >    if(h == NULL) {
> >       perror("malloc()");
> >       exit(1);
> >    }
> >
> >    h->obj_size = s;
> >    h->arena_size = n;
> >    h->free = n;
> >
> >    h->arena = malloc(s * n);
> >    if(h->arena == NULL) {
> >       perror("malloc()");
> >       exit(1);
> >    }
> >
> >    h->free_list = 0;
> >
> >    for(i = 0; i<  n; i++)
> >       *((int *) arena_obj_addr(h, i)) = i + 1;
> >
> >    *((int *) arena_obj_addr(h, i)) = -1;
> 
> This writes past the end of the allocated block.

Ha, you're right.  The original code this is based on doesn't have
that problem.  The for(;;) comparison should be i < (n - 1).  Since I
wrote it in less than an hour, there ought to be several good bugs in
there.
 
> >    return(h); 
> >}
> >
> >
> >typedef unsigned long long int T64;
> >
> >#define processcputime(p)                                                  
> >\
> 
> Why go the the trouble of declaring this as a messy macro?

I'm not all that interested in nanosecond resolution for timing
things, so I scaled the resolution down to microseconds and turned it
into a 64-bit quantity so arithmetic calculations would be more
convenient.  I suppose it could be a function call, but inline it
probably generates ten or so instructions.  Insulating the actual
system function call also makes porting a little easier.



Regards,

Uncle Steve

-- 
Should a professional politician be charged with molestation if he
kisses babies while attending political rallies?

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


#4501

FromIan Collins <ian-news@hotmail.com>
Date2011-05-22 08:50 +1200
Message-ID<93qmsmF1bbU17@mid.individual.net>
In reply to#4494
On 05/22/11 03:13 AM, Uncle Steve wrote:
> On Sat, May 21, 2011 at 02:30:39PM +1200, Ian Collins wrote:
>> On 05/20/11 10:34 AM, Uncle Steve wrote:
>>>
>>> typedef unsigned long long int T64;
>>>
>>> #define processcputime(p)
>>> \
>>
>> Why go the the trouble of declaring this as a messy macro?
>
> I'm not all that interested in nanosecond resolution for timing
> things, so I scaled the resolution down to microseconds and turned it
> into a 64-bit quantity so arithmetic calculations would be more
> convenient.  I suppose it could be a function call, but inline it
> probably generates ten or so instructions.

No more or less than an inlined function call.

> Insulating the actual
> system function call also makes porting a little easier.

But doing so in a macro makes it harder!

-- 
Ian Collins

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


#4504

FromUncle Steve <stevet810@gmail.com>
Date2011-05-21 20:03 -0400
Message-ID<e3fe3d2160801c5-77e43@gmail.com>
In reply to#4501
On Sun, May 22, 2011 at 08:50:26AM +1200, Ian Collins wrote:
> On 05/22/11 03:13 AM, Uncle Steve wrote:
> >On Sat, May 21, 2011 at 02:30:39PM +1200, Ian Collins wrote:
> >>On 05/20/11 10:34 AM, Uncle Steve wrote:
> >>>
> >>>typedef unsigned long long int T64;
> >>>
> >>>#define processcputime(p)
> >>>\
> >>
> >>Why go the the trouble of declaring this as a messy macro?
> >
> >I'm not all that interested in nanosecond resolution for timing
> >things, so I scaled the resolution down to microseconds and turned it
> >into a 64-bit quantity so arithmetic calculations would be more
> >convenient.  I suppose it could be a function call, but inline it
> >probably generates ten or so instructions.
> 
> No more or less than an inlined function call.

Right, so what's the problem?

> >Insulating the actual
> >system function call also makes porting a little easier.
> 
> But doing so in a macro makes it harder!

Not really.  Maybe what I don't get is what you mean by 'harder'.
Is 'harder' some ineffable quality that in a more robust age would
serve to differentiate the men from the boys?  I like to think so, but
I don't think it's a popular view.



Regards,

Uncle Steve

-- 
Should a professional politician be charged with molestation if he
kisses babies while attending political rallies?

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


#4506

FromIan Collins <ian-news@hotmail.com>
Date2011-05-22 13:23 +1200
Message-ID<93r6sfF1bbU20@mid.individual.net>
In reply to#4504
On 05/22/11 12:03 PM, Uncle Steve wrote:
> On Sun, May 22, 2011 at 08:50:26AM +1200, Ian Collins wrote:
>> On 05/22/11 03:13 AM, Uncle Steve wrote:
>>> On Sat, May 21, 2011 at 02:30:39PM +1200, Ian Collins wrote:
>>>> On 05/20/11 10:34 AM, Uncle Steve wrote:
>>>>>
>>>>> typedef unsigned long long int T64;
>>>>>
>>>>> #define processcputime(p)
>>>>> \
>>>>
>>>> Why go the the trouble of declaring this as a messy macro?
>>>
>>> I'm not all that interested in nanosecond resolution for timing
>>> things, so I scaled the resolution down to microseconds and turned it
>>> into a 64-bit quantity so arithmetic calculations would be more
>>> convenient.  I suppose it could be a function call, but inline it
>>> probably generates ten or so instructions.
>>
>> No more or less than an inlined function call.
>
> Right, so what's the problem?

Using a macro where a function would do.

>>> Insulating the actual
>>> system function call also makes porting a little easier.
>>
>> But doing so in a macro makes it harder!
>
> Not really.  Maybe what I don't get is what you mean by 'harder'.
> Is 'harder' some ineffable quality that in a more robust age would
> serve to differentiate the men from the boys?  I like to think so, but
> I don't think it's a popular view.

Well there's more to type (all those pesky line continuation characters 
to line up), no way to step in if you have a bug you can't easily 
diagnose and stylistic limits imposed by a macro.  The function would be 
more concise if it could return its result.

-- 
Ian Collins

[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