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


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

Casts on lvalues

Started by"BartC" <bc@freeuk.com>
First post2012-12-02 13:23 +0000
Last post2012-12-07 16:54 +0000
Articles 20 on this page of 77 — 21 participants

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


Contents

  Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-02 13:23 +0000
    Re: Casts on lvalues SG <sgesemann@gmail.invalid> - 2012-12-02 14:40 +0100
    Re: Casts on lvalues Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-12-02 13:53 +0000
      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-06 12:26 +0000
        Re: Casts on lvalues Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-12-06 15:15 +0000
        Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-06 12:05 -0800
    Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-02 12:34 -0800
      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-02 21:18 +0000
        Re: Casts on lvalues Willem <willem@turtle.stack.nl> - 2012-12-05 22:36 +0000
          Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 23:46 +0000
            Re: Casts on lvalues Willem <willem@turtle.stack.nl> - 2012-12-06 18:35 +0000
      Re: Casts on lvalues pete <pfiland@mindspring.com> - 2012-12-02 16:21 -0500
        Re: Casts on lvalues Eric Sosman <esosman@comcast-dot-net.invalid> - 2012-12-02 17:10 -0500
          Re: Casts on lvalues pete <pfiland@mindspring.com> - 2012-12-02 18:50 -0500
        Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-02 19:14 -0500
    Re: Casts on lvalues falk@rahul.net (Edward A. Falk) - 2012-12-04 23:57 +0000
      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 01:35 +0000
        Re: Casts on lvalues Piotr Kalinowski <pitkali@gmail.com> - 2012-12-05 16:07 +0100
          Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 16:47 +0000
            Re: Casts on lvalues Eric Sosman <esosman@comcast-dot-net.invalid> - 2012-12-05 13:04 -0500
              Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 18:39 +0000
                Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-05 14:23 -0500
                  Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 22:11 +0000
                    Re: Casts on lvalues Ian Collins <ian-news@hotmail.com> - 2012-12-06 11:51 +1300
                      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 23:58 +0000
                        Re: Casts on lvalues Piotr Kalinowski <pitkali@gmail.com> - 2012-12-06 22:00 +0100
                    Re: Casts on lvalues glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2012-12-06 03:05 +0000
                Re: Casts on lvalues Eric Sosman <esosman@comcast-dot-net.invalid> - 2012-12-05 14:43 -0500
                Re: Casts on lvalues Greg Martin <greg@softsprocket.com> - 2012-12-05 12:25 -0800
                  Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 21:57 +0000
                    Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-05 16:09 -0800
                      Re: Casts on lvalues Philipp Thomas <kthomas@linux01.gwdg.de> - 2012-12-07 01:24 +0100
                        Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-06 17:22 -0800
                          Re: Casts on lvalues Öö Tiib <ootiib@hot.ee> - 2012-12-07 00:31 -0800
                            Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-07 08:18 -0500
                              Re: Casts on lvalues Öö Tiib <ootiib@hot.ee> - 2012-12-07 09:07 -0800
                            Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-07 11:01 -0800
                              Re: Casts on lvalues glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2012-12-07 21:57 +0000
                                Re: Casts on lvalues Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-12-07 22:29 +0000
                                  Re: Casts on lvalues glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2012-12-08 00:04 +0000
                              Re: Casts on lvalues lawrence.jones@siemens.com - 2012-12-15 16:51 -0500
                                Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-15 15:48 -0800
                                  Re: Casts on lvalues lawrence.jones@siemens.com - 2012-12-17 16:37 -0500
                              Re: Casts on lvalues Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-17 02:58 -0800
                            Re: Casts on lvalues Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-17 02:53 -0800
                          Re: Casts on lvalues Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-17 02:43 -0800
                Re: Casts on lvalues Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-12-05 22:07 +0000
                  Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-05 22:20 +0000
                    Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-05 16:10 -0800
                    Re: Casts on lvalues Philip Lantz <prl@canterey.us> - 2012-12-06 22:49 -0800
                      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 12:54 +0000
                        Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-07 08:22 -0500
                          Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 13:48 +0000
                            Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-07 11:17 -0500
                              Re: Casts on lvalues glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2012-12-07 17:33 +0000
                                Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 18:28 +0000
                                  Re: Casts on lvalues glen herrmannsfeldt <gah@ugcs.caltech.edu> - 2012-12-07 22:18 +0000
                              Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 18:27 +0000
                                Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-07 14:14 -0500
                                  Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 20:16 +0000
                                    Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-07 15:41 -0500
                                      Re: Casts on lvalues Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-17 03:03 -0800
                Re: Casts on lvalues Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2012-12-09 17:54 +0200
                  Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-09 12:38 -0500
                    Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-09 18:50 +0000
                      Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-09 14:31 -0500
                        Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-09 20:12 -0800
                          Re: Casts on lvalues Heikki Kallasjoki <fis+usenet@zem.fi> - 2012-12-10 07:38 +0000
                            Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-10 08:12 -0500
                              Re: Casts on lvalues Heikki Kallasjoki <fis+usenet@zem.fi> - 2012-12-10 17:46 +0000
                                Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-10 12:59 -0500
                                Re: Casts on lvalues Keith Thompson <kst-u@mib.org> - 2012-12-10 12:07 -0800
                              Re: Casts on lvalues Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-17 03:11 -0800
                          Re: Casts on lvalues Ian Collins <ian-news@hotmail.com> - 2012-12-10 20:50 +1300
                          Re: Casts on lvalues James Kuyper <jameskuyper@verizon.net> - 2012-12-10 07:49 -0500
    Re: Casts on lvalues Rui Maciel <rui.maciel@gmail.com> - 2012-12-07 15:19 +0000
      Re: Casts on lvalues "BartC" <bc@freeuk.com> - 2012-12-07 16:54 +0000

Page 1 of 4  [1] 2 3 4  Next page →


#28872 — Casts on lvalues

From"BartC" <bc@freeuk.com>
Date2012-12-02 13:23 +0000
SubjectCasts on lvalues
Message-ID<xDIus.482873$GX.378393@fx01.am4>
Suppose I have these types:

#define byte unsigned char

typedef struct {
 int a,b,c,d;
} R;               /* assume this is 16 bytes */

And these variables:

int n;             /* represents a *byte* offset */
R* p;

I want to be able to do the following:
 p += n;

but it doesn't work because n is a byte offset; it's not in terms of R
objects. But the obvious cast:

 (byte*)p+=n;

doesn't appear to compile.  The workarounds seem to be:

 p += n/sizeof(R);

which I don't like. Even though p is always aligned (and n is known to be a
multiple of 16), and I know the divide will cancel out, it seems funny 
having to introduce a divide op in the first place. And:

 p = (R*)((byte*)p+n);

which is what I'm using but looks very untidy in real code.

In any case, the question remains, *is* there a way to cast an lvalue as
I've shown above?

-- 
Bartc  

[toc] | [next] | [standalone]


#28873

FromSG <sgesemann@gmail.invalid>
Date2012-12-02 14:40 +0100
Message-ID<k9flp4$pme$1@news.albasani.net>
In reply to#28872
Am 02.12.2012 14:23, schrieb BartC:
> Suppose I have these types:
> 
> #define byte unsigned char
> 
> typedef struct {
> int a,b,c,d;
> } R;               /* assume this is 16 bytes */
> 
> And these variables:
> 
> int n;             /* represents a *byte* offset */
> R* p;
> 
> I want to be able to do the following:
> p += n;
> 
> but it doesn't work because n is a byte offset; it's not in terms of R
> objects. But the obvious cast:
> 
> (byte*)p+=n;
> 
> doesn't appear to compile.  The workarounds seem to be:
> 
> p += n/sizeof(R);
> 
> which I don't like. Even though p is always aligned (and n is known to be a
> multiple of 16), and I know the divide will cancel out, it seems funny
> having to introduce a divide op in the first place. And:
> 
> p = (R*)((byte*)p+n);
> 
> which is what I'm using but looks very untidy in real code.
> 
> In any case, the question remains, *is* there a way to cast an lvalue as
> I've shown above?

In C++ there is.  But you would invoke undefined behaviour because doing
it in this case violates the aliasing rule.  I really don't see the
problem with

  p += n/sizeof(R);

It looks like exactly the thing you should write.  Maybe throw an

  assert(n % sizeof(R) == 0);

in there as well.

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


#28874

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2012-12-02 13:53 +0000
Message-ID<0.8897a175ed58fc93c71b.20121202135321GMT.87txs4lfvy.fsf@bsb.me.uk>
In reply to#28872
"BartC" <bc@freeuk.com> writes:

> Suppose I have these types:
>
> #define byte unsigned char
>
> typedef struct {
> int a,b,c,d;
> } R;               /* assume this is 16 bytes */
>
> And these variables:
>
> int n;             /* represents a *byte* offset */
> R* p;
>
> I want to be able to do the following:
> p += n;
>
> but it doesn't work because n is a byte offset; it's not in terms of R
> objects. But the obvious cast:
>
> (byte*)p+=n;
>
> doesn't appear to compile.  The workarounds seem to be:
>
> p += n/sizeof(R);
>
> which I don't like. Even though p is always aligned (and n is known to be a
> multiple of 16), and I know the divide will cancel out, it seems funny
> having to introduce a divide op in the first place. And:
>
> p = (R*)((byte*)p+n);
>
> which is what I'm using but looks very untidy in real code.
>
> In any case, the question remains, *is* there a way to cast an lvalue as
> I've shown above?

No, I don't think so.  Certainly not directly -- a cast expression is
not a lvalue.  You can do dangerous thing like:

  *(byte **)&p += n;  /* don't do this!! */

or use a union with an R * and a char * pointer in it, but both
techniques rely on the representation of char and struct pointers being
the same -- they re-interpret the pointer rather than converting it.

I think your best bet is to tidy up what you currently use

  static inline void *addr_inc(void *p, int n) { return (char *)p + n; }

will let you write p = addr_inc(p, n); which is much less messy and not
hard to follow.

-- 
Ben.

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


#28974

From"BartC" <bc@freeuk.com>
Date2012-12-06 12:26 +0000
Message-ID<X90ws.515373$nB6.114818@fx21.am4>
In reply to#28874
"Ben Bacarisse" <ben.usenet@bsb.me.uk> wrote in message
news:0.8897a175ed58fc93c71b.20121202135321GMT.87txs4lfvy.fsf@bsb.me.uk...
> "BartC" <bc@freeuk.com> writes:

>> (byte*)p+=n;

>> In any case, the question remains, *is* there a way to cast an lvalue as
>> I've shown above?
>
> No, I don't think so.  Certainly not directly -- a cast expression is
> not a lvalue.  You can do dangerous thing like:
>
>  *(byte **)&p += n;  /* don't do this!! */
>
> or use a union with an R * and a char * pointer in it, but both
> techniques rely on the representation of char and struct pointers being
> the same -- they re-interpret the pointer rather than converting it.

I saw your comment and didn't look much further (I thought the dangers were
something to do with aliasing). Yet this seems exactly what I was looking
for.

So if someone wants an lvalue cast of the form (T)A, they can just do 
*(T*)&A
instead. (Provided they know that, for example, pointer representations
happen to be compatible.)

So this statement:

"Keith Thompson" <kst-u@mib.org> wrote in message
news:lnwqwwoxac.fsf@nuthaus.mib.org...

> C doesn't have lvalue casts.

isn't completely true, because it seems you can get around it easily by
turning it into an rvalue cast first. (Also I'm talking about type-punning
sorts of casts rather than type-conversion ones.)

-- 
Bartc 

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


#28984

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2012-12-06 15:15 +0000
Message-ID<0.6d430ae5bbbc9ae83f39.20121206151513GMT.87lidbnrem.fsf@bsb.me.uk>
In reply to#28974
"BartC" <bc@freeuk.com> writes:

> "Ben Bacarisse" <ben.usenet@bsb.me.uk> wrote in message
> news:0.8897a175ed58fc93c71b.20121202135321GMT.87txs4lfvy.fsf@bsb.me.uk...
>> "BartC" <bc@freeuk.com> writes:
>
>>> (byte*)p+=n;
>
>>> In any case, the question remains, *is* there a way to cast an lvalue as
>>> I've shown above?
>>
>> No, I don't think so.  Certainly not directly -- a cast expression is
>> not a lvalue.  You can do dangerous thing like:
>>
>>  *(byte **)&p += n;  /* don't do this!! */
>>
>> or use a union with an R * and a char * pointer in it, but both
>> techniques rely on the representation of char and struct pointers being
>> the same -- they re-interpret the pointer rather than converting it.
>
> I saw your comment and didn't look much further (I thought the dangers were
> something to do with aliasing). Yet this seems exactly what I was looking
> for.
>
> So if someone wants an lvalue cast of the form (T)A, they can just do
> *(T*)&A instead.

The depends on the meaning you give to "lvalue cast".  Since C does not
have such a thing, you have to specify it, but your original posted used
code that had different semantics.  That's why, in part, I said "don't
do this" -- because it does not have the same meaning as the code you
presented.

> (Provided they know that, for example, pointer representations
> happen to be compatible.)

It seems odd to assume this when you don't need to.  Your original post
complained only about the fact that your solution was rather wordy (or
messy -- I don't recall exactly), so I suggested an inline function to
tidy it up.  Why would you exchange a universal solution for one with a
restriction?

> So this statement:
>
> "Keith Thompson" <kst-u@mib.org> wrote in message
> news:lnwqwwoxac.fsf@nuthaus.mib.org...
>
>> C doesn't have lvalue casts.
>
> isn't completely true, because it seems you can get around it easily by
> turning it into an rvalue cast first.

It's still completely true.  C does not have pass by reference either,
and any technique used to get round that restriction does not alter that
fact.

> (Also I'm talking about type-punning
> sorts of casts rather than type-conversion ones.)

OK, but how could anyone have known?  The code you originally posted
used entirely portable type-conversions.

-- 
Ben.

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


#28992

FromKeith Thompson <kst-u@mib.org>
Date2012-12-06 12:05 -0800
Message-ID<lnsj7josix.fsf@nuthaus.mib.org>
In reply to#28974
"BartC" <bc@freeuk.com> writes:
[...]
> So this statement:
>
> "Keith Thompson" <kst-u@mib.org> wrote in message
> news:lnwqwwoxac.fsf@nuthaus.mib.org...
>
>> C doesn't have lvalue casts.
>
> isn't completely true, because it seems you can get around it easily by
> turning it into an rvalue cast first. (Also I'm talking about type-punning
> sorts of casts rather than type-conversion ones.)

Yes, it is completely true.

C doesn't have linked lists or binary trees either, but you can
easily implement them using structs and pointers.  C gives you the
basic tools needed to build just about *anything*.  Lvalue casts
(whatever you happen to mean by that phrase) are not one of those
basic tools, but they are something you can build.

And please keep in mind that there's a *big* difference between
conversion and type-punning.  Conversion, as implemented by
a cast operator, converts a *value* from one type to another.
For example, a conversion from int to float gives you a float
with the mathematical value of the operand, regardless of how ints
and floats are represented.  Pointer conversions conceptually do
the same thing; it just happens that most modern implementations
represent all pointers the same way, so pointer conversions can be
implemented as a reinterpretation of the representation.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#28882

FromKeith Thompson <kst-u@mib.org>
Date2012-12-02 12:34 -0800
Message-ID<lny5hg8a7r.fsf@nuthaus.mib.org>
In reply to#28872
"BartC" <bc@freeuk.com> writes:
> Suppose I have these types:
>
> #define byte unsigned char

Why are you using a macro rather than a typedef?

> typedef struct {
>  int a,b,c,d;
> } R;               /* assume this is 16 bytes */

Or you could assume that it's `sizeof R` bytes.

> And these variables:
>
> int n;             /* represents a *byte* offset */
> R* p;
>
> I want to be able to do the following:
>  p += n;
>
> but it doesn't work because n is a byte offset; it's not in terms of R
> objects. But the obvious cast:
>
>  (byte*)p+=n;
>
> doesn't appear to compile.

Right.  A cast operator doesn't require an lvalue as its operand.
If the operand happens to be an lvalue, it's not treated as one.
It undergoes an "lvalue conversion" as described in N1570 6.3.2.1p2.
The result of a cast is not an lvalue.

>                             The workarounds seem to be:
>
>  p += n/sizeof(R);
>
> which I don't like. Even though p is always aligned (and n is known to be a
> multiple of 16), and I know the divide will cancel out, it seems funny 
> having to introduce a divide op in the first place. And:
>
>  p = (R*)((byte*)p+n);
>
> which is what I'm using but looks very untidy in real code.
>
> In any case, the question remains, *is* there a way to cast an lvalue as
> I've shown above?

No.

Why is n a byte offset in the first place?  You're dealing with
objects of your anonymous struct type; can't you just give your
struct a name and make p a pointer to it?  If you need a byte
pointer, you can convert a struct pointer to byte*.

Incidentally, I'd probably use unsigned char directly; it's clear enough
and doesn't make the reader wonder how "byte" has been defined.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

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


#28886

From"BartC" <bc@freeuk.com>
Date2012-12-02 21:18 +0000
Message-ID<4BPus.800532$EF4.173275@fx23.am4>
In reply to#28882
"Keith Thompson" <kst-u@mib.org> wrote in message 
news:lny5hg8a7r.fsf@nuthaus.mib.org...
> "BartC" <bc@freeuk.com> writes:

>> int n;             /* represents a *byte* offset */
>> R* p;
>>
>> I want to be able to do the following:
>>  p += n;
>>
>> but it doesn't work because n is a byte offset; it's not in terms of R
>> objects. But the obvious cast:

> Why is n a byte offset in the first place?

The offsets come from externally generated data, and initially were simple 
counts: +2, -1 etc. The code looked like this:

 R *p,*q;

 p=q+n;

Very nice. Then I noticed this addition involved internally multiplying n by 
16 (or a shift as it was), which wasn't so nice! It was just as easy to 
generate these numbers as multiples of 16 anyway (+32, -16 etc) so I did 
that. But then the code wasn't so pretty.

-- 
Bartc 

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


#28961

FromWillem <willem@turtle.stack.nl>
Date2012-12-05 22:36 +0000
Message-ID<slrnkbvj42.jen.willem@turtle.stack.nl>
In reply to#28886
BartC wrote:
) The offsets come from externally generated data, and initially were simple 
) counts: +2, -1 etc. The code looked like this:
)
)  R *p,*q;
)
)  p=q+n;
)
) Very nice. Then I noticed this addition involved internally multiplying n by 
) 16 (or a shift as it was), which wasn't so nice! It was just as easy to 
) generate these numbers as multiples of 16 anyway (+32, -16 etc) so I did 
) that. But then the code wasn't so pretty.

That's quite odd.  A good compiler should have done that optimization for
you, if it's at all possible.  Also, on x86 CPU's, there are addressing
modes that implicitly multiply by factors of two, with no speed penalty.

And, obviously, this is pretty much a micro optimization.  Are you that
concerned with execution speed?  Is this for some embedded cpu?


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

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


#28963

From"BartC" <bc@freeuk.com>
Date2012-12-05 23:46 +0000
Message-ID<k1Rvs.1060147$ti6.214777@fx20.am4>
In reply to#28961

"Willem" <willem@turtle.stack.nl> wrote in message
news:slrnkbvj42.jen.willem@turtle.stack.nl...
> BartC wrote:
> ) The offsets come from externally generated data, and initially were
> simple
> ) counts: +2, -1 etc. The code looked like this:
> )
> )  R *p,*q;
> )
> )  p=q+n;
> )
> ) Very nice. Then I noticed this addition involved internally multiplying
> n by
> ) 16 (or a shift as it was), which wasn't so nice! It was just as easy to
> ) generate these numbers as multiples of 16 anyway (+32, -16 etc) so I did
> ) that. But then the code wasn't so pretty.
>
> That's quite odd.  A good compiler should have done that optimization for
> you, if it's at all possible.  Also, on x86 CPU's, there are addressing
> modes that implicitly multiply by factors of two, with no speed penalty.

How can it be optimised? If the pointer has a 16-byte stride, and you're
adding an offset N, then N*16 must be added to the pointer. The x86's
address scaling feature only goes up to *8. This *16 is implemented with a
shift.

> And, obviously, this is pretty much a micro optimization.  Are you that
> concerned with execution speed?  Is this for some embedded cpu?

As it happened, it made very little difference (about 0.4% better), even
though this unnecessary operation was executed some 80 million times every
second. But sometimes you are just making dozens of tiny improvements which
together make a worthwhile difference. (Sometimes, they inexplicably make
things slower too.)

But I just don't like the idea of my code (and the instruction cache)
getting cluttered up with things that don't need to be there. I doubt they 
will make it go faster!

(And yes I am hoping to get this working on a slow-running board computer --
one day.)

-- 
Bartc 

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


#28990

FromWillem <willem@turtle.stack.nl>
Date2012-12-06 18:35 +0000
Message-ID<slrnkc1pbr.rll.willem@turtle.stack.nl>
In reply to#28963
BartC wrote:
)
)
) "Willem" <willem@turtle.stack.nl> wrote in message
) news:slrnkbvj42.jen.willem@turtle.stack.nl...
)> BartC wrote:
)> ) The offsets come from externally generated data, and initially were
)> simple
)> ) counts: +2, -1 etc. The code looked like this:
)> )
)> )  R *p,*q;
)> )
)> )  p=q+n;
)> )
)> ) Very nice. Then I noticed this addition involved internally multiplying
)> n by
)> ) 16 (or a shift as it was), which wasn't so nice! It was just as easy to
)> ) generate these numbers as multiples of 16 anyway (+32, -16 etc) so I did
)> ) that. But then the code wasn't so pretty.
)>
)> That's quite odd.  A good compiler should have done that optimization for
)> you, if it's at all possible.  Also, on x86 CPU's, there are addressing
)> modes that implicitly multiply by factors of two, with no speed penalty.
)
) How can it be optimised? If the pointer has a 16-byte stride, and you're
) adding an offset N, then N*16 must be added to the pointer.

I was under the impression that you were generating the offsets somewhere.
If you can pre-multiply those by 16, so can the compiler, one would think.

Take, for example:
  
  int step = some_function();
  struct struct_16_bytes_long p = start;
  while (p->marker != 0) {
    frobnicate(p->data);
    p += step;
  }

In this case, the optimizer should pull the multiply-by-16 out of the loop,
shouldn't it?


) The x86's address scaling feature only goes up to *8. This *16 is
) implemented with a shift.

I wasn't aware the stride was 16 bytes.


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT

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


#28887

Frompete <pfiland@mindspring.com>
Date2012-12-02 16:21 -0500
Message-ID<50BBC645.3780@mindspring.com>
In reply to#28882
Keith Thompson wrote:

> The result of a cast is not an lvalue.

I don't think that the standard explicitly states this;
but as far as I can tell,
the result of any conversion of the type of any expression, 
is not an lvalue.

-- 
pete

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


#28890

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2012-12-02 17:10 -0500
Message-ID<k9gjk1$bkm$1@dont-email.me>
In reply to#28887
On 12/2/2012 4:21 PM, pete wrote:
> Keith Thompson wrote:
>
>> The result of a cast is not an lvalue.
>
> I don't think that the standard explicitly states this;

     It's in a footnote to 6.5.4p5.  Footnotes are non-normative,
but then there's the definition of lvalue in 6.3.2.1p1:

	"An lvalue is an expression [...] that potentially
	designates an object [...]"

There is no cast that produces an object designator,[*] hence
there is no cast that produces an lvalue.

     [*] You can (sometimes) derive an lvalue from the result
of a cast by applying an operator to it, as in

	* (unsigned char*)&foo = 42;

or
	((struct baz*)&foo) -> mumble = 17;

> but as far as I can tell,
> the result of any conversion of the type of any expression,
> is not an lvalue.

     Even a non-conversion is not an lvalue:

	double trouble;
	(double)trouble = 3.14;  // BZZZT!

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

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


#28893

Frompete <pfiland@mindspring.com>
Date2012-12-02 18:50 -0500
Message-ID<50BBE95D.268A@mindspring.com>
In reply to#28890
Eric Sosman wrote:
> 
> On 12/2/2012 4:21 PM, pete wrote:
> > Keith Thompson wrote:
> >
> >> The result of a cast is not an lvalue.
> >
> > I don't think that the standard explicitly states this;
> 
>      It's in a footnote to 6.5.4p5.  Footnotes are non-normative,
> but then there's the definition of lvalue in 6.3.2.1p1:
> 
>         "An lvalue is an expression [...] that potentially
>         designates an object [...]"
> 
> There is no cast that produces an object designator,[*] hence
> there is no cast that produces an lvalue.
> 
>      [*] You can (sometimes) derive an lvalue from the result
> of a cast by applying an operator to it, as in
> 
>         * (unsigned char*)&foo = 42;
> 
> or
>         ((struct baz*)&foo) -> mumble = 17;
> 
> > but as far as I can tell,
> > the result of any conversion of the type of any expression,
> > is not an lvalue.
> 
>      Even a non-conversion is not an lvalue:
> 
>         double trouble;
>         (double)trouble = 3.14;  // BZZZT!

The other type conversion that I was thinking of,
was the implicit conversion of an array type.

-- 
pete

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


#28894

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-12-02 19:14 -0500
Message-ID<k9gqsh$mb5$1@dont-email.me>
In reply to#28887
On 12/02/2012 04:21 PM, pete wrote:
> Keith Thompson wrote:
> 
>> The result of a cast is not an lvalue.
> 
> I don't think that the standard explicitly states this;
> but as far as I can tell,
> the result of any conversion of the type of any expression, 
> is not an lvalue.

The standard says that something is not an lvalue in only a few places:
6.3.2.1p3 when an lvalue of array type is converted to a pointer to its
first element.
6.5.2.3p3 function_returning_struct_type().member
6.5.16p3 assignment expression

Most of the time, it only says when something IS an lvalue:
6.5.1p2	object_identifier
6.5.1p4 "string literal"
6.5.1p5 (lvalue)
6.5.1.1p4 _Generic(x, int:lvalue1, default:lvalue2)
6.5.2.3p3 lvalue.member
6.5.2.3p4 expression->member
6.5.2.5p4 compound literal
6.5.3.4p4 *pointer_to_object
6.9.1p9 function parameter identifier
-- 
James Kuyper

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


#28921

Fromfalk@rahul.net (Edward A. Falk)
Date2012-12-04 23:57 +0000
Message-ID<k9m2m6$vfu$1@blue-new.rahul.net>
In reply to#28872
In article <xDIus.482873$GX.378393@fx01.am4>, BartC <bc@freeuk.com> wrote:
>
>I want to be able to do the following:
> p += n;
>
>but it doesn't work because n is a byte offset; it's not in terms of R
>objects. But the obvious cast:
>
> (byte*)p+=n;
>
>doesn't appear to compile.  The workarounds seem to be:
>
> p += n/sizeof(R);

Other options:

p += n/sizeof(*p);

p = (R *)((byte *)p +n)

But frankly, none of these is a very good choice.  If I were
code-reviewing something like this, I'd ask the programmer what it is
that they're *really* trying to do.  Constructs like this are
a likely sign of broken logic and broken code.

Note also that the n/sizeof(...) variant fails horribly if the
byte offset isn't a multiple of the structure size.

Not to say that something like this should *never* be written --
I can think of a number of cases where multiple data structures
might be packed into a buffer, in which case this is exactly the
sort of thing you might be doing.  But in cases like this, you're
best off keeping p as a byte pointer and just casting it to a
pointer to R when you need to dereference it.

I'm assuming you're taking the proper precautions w.r.t. alignment
issues.  That's a whole 'nother discussion.

-- 
	-Ed Falk, falk@despams.r.us.com
	http://thespamdiaries.blogspot.com/

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


#28928

From"BartC" <bc@freeuk.com>
Date2012-12-05 01:35 +0000
Message-ID<sxxvs.687666$9H4.316060@fx17.am4>
In reply to#28921
"Edward A. Falk" <falk@rahul.net> wrote in message 
news:k9m2m6$vfu$1@blue-new.rahul.net...
> In article <xDIus.482873$GX.378393@fx01.am4>, BartC <bc@freeuk.com> wrote:
>>
>>I want to be able to do the following:
>> p += n;
>>
>>but it doesn't work because n is a byte offset; it's not in terms of R

> Other options:
>
> p += n/sizeof(*p);
>
> p = (R *)((byte *)p +n)
>
> But frankly, none of these is a very good choice.  If I were
> code-reviewing something like this, I'd ask the programmer what it is
> that they're *really* trying to do.  Constructs like this are
> a likely sign of broken logic and broken code.

I've already said elsewhere that using an object rather than a byte offset 
involved an unnecessary multiplication or shift.

I noticed it when I wanted shadow some functions with assembly code.

-- 
Bartc 

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


#28946

FromPiotr Kalinowski <pitkali@gmail.com>
Date2012-12-05 16:07 +0100
Message-ID<m2sj7kmtab.fsf@gmail.com>
In reply to#28928
"BartC" <bc@freeuk.com> writes:

> "Edward A. Falk" <falk@rahul.net> wrote in message
> news:k9m2m6$vfu$1@blue-new.rahul.net...
> I've already said elsewhere that using an object rather than a byte
> offset involved an unnecessary multiplication or shift.

It was not unnecessary. It's called pointer arithmetic and allowed you
to use more elegant code at slightly higher level of abstraction that
is supposed to more closely represent your intentions.

You have decided this abstraction is unnecessary, because you feel you
need to optimise this shift/multiplication away (and maybe you do, I
couldn't possibly know that). More specifically, you have implicitly
decided this optimisation is worth the trade off in form of increased
complexity of the code (decreased readability or whatever it is that
bugged you enough to actually ask about it, seeking a different way to
express what you are doing).

There's no free lunch. Now deal with the consequences, or revert your
decision, as others already presented answer to your original question.

Regards,
Piotr Kalinowski

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


#28948

From"BartC" <bc@freeuk.com>
Date2012-12-05 16:47 +0000
Message-ID<tVKvs.786834$A%.8284@fx26.am4>
In reply to#28946

"Piotr Kalinowski" <pitkali@gmail.com> wrote in message 
news:m2sj7kmtab.fsf@gmail.com...
> "BartC" <bc@freeuk.com> writes:
>
>> I've already said elsewhere that using an object rather than a byte
>> offset involved an unnecessary multiplication or shift.
>
> It was not unnecessary. It's called pointer arithmetic and allowed you
> to use more elegant code at slightly higher level of abstraction that
> is supposed to more closely represent your intentions.

Yet, C allows to you to do this - cast the target of a pointer - in an 
rvalue expression.

> You have decided this abstraction is unnecessary, because you feel you
> need to optimise this shift/multiplication away (and maybe you do, I
> couldn't possibly know that). More specifically, you have implicitly
> decided this optimisation is worth the trade off in form of increased
> complexity of the code (decreased readability or whatever it is that
> bugged you enough to actually ask about it, seeking a different way to
> express what you are doing).

I asked about doing the same on the left side of an assignment.

It's this asymmetry that is the issue.

-- 
Bartc 

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


#28950

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2012-12-05 13:04 -0500
Message-ID<k9o2b3$bcb$1@dont-email.me>
In reply to#28948
On 12/5/2012 11:47 AM, BartC wrote:
>
> Yet, C allows to you to do this - cast the target of a pointer - in an
> rvalue expression.

     No: C allows you to apply a cast operator to a *value* (which
may have been extracted from a pointer's target), not to the target
itself.

>[...]
> I asked about doing the same on the left side of an assignment.
>
> It's this asymmetry that is the issue.

     Um, er, assignment itself is asymmetric ...

-- 
Eric Sosman
esosman@comcast-dot-net.invalid

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


Page 1 of 4  [1] 2 3 4  Next page →

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


csiph-web