473,396 Members | 1,785 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

anti-aliasing

A proposed new function

int alias(void *ptr1, size_t len1, void *ptr1, size_t len2)

Returns true if the pointers overlap.

On most machines it can be trivially implemented. However it has to be a
standard library function because it is not necessarily legal to compare two
address from different objects.

The advantages:

An unintelligent implementation simply executes the user's error-handling
code if an unwanted alias is passed. An intelligent implementation can
detect that the two pointers cannot possibly be aliases, and generate moe
efficient code.

However the restrictions do not percolate up to calling code. There is no
need to declare every pointer parameter "restict" just because somewhere you
call a library string copy.
Feb 10 '07 #1
53 3811
Malcolm McLean wrote:
A proposed new function

int alias(void *ptr1, size_t len1, void *ptr1, size_t len2)

Returns true if the pointers overlap.
Who will specify the len1 and len2 parameters?

Feb 10 '07 #2

"Malcolm McLean" <re*******@btinternet.comwrote in message
news:4_******************************@bt.com...
>A proposed new function

int alias(void *ptr1, size_t len1, void *ptr1, size_t len2)

Returns true if the pointers overlap.

On most machines it can be trivially implemented. However it has to be a
standard library function because it is not necessarily legal to compare
two address from different objects.

The advantages:

An unintelligent implementation simply executes the user's error-handling
code if an unwanted alias is passed. An intelligent implementation can
detect that the two pointers cannot possibly be aliases, and generate moe
efficient code.

However the restrictions do not percolate up to calling code. There is no
need to declare every pointer parameter "restict" just because somewhere
you call a library string copy.
Not sure about the use of such a function. aliasing is about compiletime
optimization. You want a compiler to generate code like:

if (alias(...))
{
// do "slow" code
}
else
{
// do "fast" code
}

not sure if that would speed things up :)
Feb 10 '07 #3
Malcolm McLean said:
A proposed new function

int alias(void *ptr1, size_t len1, void *ptr1, size_t len2)
invades my namespace. Please call it something else, e.g. isalias.

Thanks.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Feb 10 '07 #4
Richard Heathfield wrote:
Malcolm McLean said:
A proposed new function

int alias(void *ptr1, size_t len1, void *ptr1, size_t len2)

invades my namespace. Please call it something else, e.g. isalias.
Unless you want to puts its declaration only in <ctype.h>, that also
invades the user namespace.

Feb 10 '07 #5

On Sat, 10 Feb 2007, Malcolm McLean wrote:
>
A proposed new function

int alias(void *ptr1, size_t len1, void *ptr1, size_t len2)

Returns true if the pointers overlap.
You mean "returns true if any of the first 'len1' bytes of the
object pointed to by 'ptr1' overlaps with any of the first 'len2'
bytes pointed to by 'ptr2'," perhaps with an exception that if
'ptr1' or 'ptr2' is null, the return value is false, or perhaps
it'd be better to leave that behavior undefined.
Basically I'm saying that we must require 'ptr1' to actually
point to an object of at least 'len1' bytes, and likewise 'ptr2'
and 'len2'.

The problem with the name (easily fixed) has been noticed already.
I'd suggest 'memalias', since this is a function that deals with blocks
of memory.

I'd prefer the function to return 1 on success, instead of merely
"true" (non-zero).
On most machines it can be trivially implemented. However it has to be a
standard library function because it is not necessarily legal to compare
two addresses from different objects.
True.
The advantages:

An unintelligent implementation simply executes the user's error-handling
code if an unwanted alias is passed. An intelligent implementation can
detect that the two pointers cannot possibly be aliases, and generate moe
efficient code.

However the restrictions do not percolate up to calling code. There is no
need to declare every pointer parameter "restict" just because somewhere you
call a library string copy.
I don't follow you. It sounds like you're describing (poorly) a
/feature/ of the new function: that the user can write

if (memalias(p1, 10, p2, 10))
memmove(p1, p2, 10);
else
memcpy(p1, p2, 10);

But that's not an /advantage/; in fact in this case (and probably in
most real-world cases with a good compiler) it's a disadvantage, because
it suggests to the user that he will get better performance from the
above obfuscated code than from a simple and readable

memmove(p1, p2, 10);

when in fact the reverse is true.

Maybe if you post an example of code that would benefit from this
new function, the advantages will become clearer.

HTH,
-Arthur
Feb 10 '07 #6

"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrote in message
>
On Sat, 10 Feb 2007, Malcolm McLean wrote:
>>
A proposed new function

int alias(void *ptr1, size_t len1, void *ptr1, size_t len2)

Returns true if the pointers overlap.

You mean "returns true if any of the first 'len1' bytes of the
object pointed to by 'ptr1' overlaps with any of the first 'len2'
bytes pointed to by 'ptr2'," perhaps with an exception that if
'ptr1' or 'ptr2' is null, the return value is false, or perhaps
it'd be better to leave that behavior undefined.
Basically I'm saying that we must require 'ptr1' to actually
point to an object of at least 'len1' bytes, and likewise 'ptr2'
and 'len2'.

The problem with the name (easily fixed) has been noticed already.
I'd suggest 'memalias', since this is a function that deals with blocks
of memory.

I'd prefer the function to return 1 on success, instead of merely
"true" (non-zero).
>On most machines it can be trivially implemented. However it has to be a
standard library function because it is not necessarily legal to compare
two addresses from different objects.

True.
>The advantages:

An unintelligent implementation simply executes the user's error-handling
code if an unwanted alias is passed. An intelligent implementation can
detect that the two pointers cannot possibly be aliases, and generate moe
efficient code.

However the restrictions do not percolate up to calling code. There is no
need to declare every pointer parameter "restict" just because somewhere
you
call a library string copy.

I don't follow you. It sounds like you're describing (poorly) a
/feature/ of the new function: that the user can write

if (memalias(p1, 10, p2, 10))
memmove(p1, p2, 10);
else
memcpy(p1, p2, 10);

But that's not an /advantage/; in fact in this case (and probably in
most real-world cases with a good compiler) it's a disadvantage, because
it suggests to the user that he will get better performance from the
above obfuscated code than from a simple and readable

memmove(p1, p2, 10);

when in fact the reverse is true.

Maybe if you post an example of code that would benefit from this
new function, the advantages will become clearer.
We've got an array of employees, and a list of candidates stored in a linked
list. When a candiate is successful, we want to copy his name over to one of
the employee fields.

Now in fact the candiadate list and the employee list cannot overlap. But
they are generated in widely dispersed parts of a big program. Using
restrict syntax

void employ(restrict EMPLOYEE *employees, int N, restrict EMPLOYEE
*candidate)

we hacve got to percolate up the restrict through all the program.

However do this

void employ(EMPLOYEE *employees, int N, EMPLOYEE *candidate)
{
if(memsame(employees, N * sizeof(EMPLOYEE), candidate, sizeof(EMPLOYEE))
{
/* something has gone deeply wrong if candidate already in our list of
employees. Debug code. */
assert(0);
}
/* compiler knows that at this point no alias */
/* call fast no-alias version of strcpy */
strcpy(emplyees[N-1].name, candidate->name);
}

Feb 10 '07 #7

On Sat, 10 Feb 2007, Malcolm McLean wrote:
"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrote in message
>On Sat, 10 Feb 2007, Malcolm McLean wrote:
>>>
A proposed new function

int alias(void *ptr1, size_t len1, void *ptr1, size_t len2)

Returns true if the pointers overlap.
[big snip]
> Maybe if you post an example of code that would benefit from this
new function, the advantages will become clearer.

We've got an array of employees, and a list of candidates stored in a linked
list. When a candiate is successful, we want to copy his name over to one of
the employee fields.

Now in fact the candiadate list and the employee list cannot overlap. But
they are generated in widely dispersed parts of a big program. Using
restrict syntax

void employ(restrict EMPLOYEE *employees, int N, restrict EMPLOYEE
*candidate)

we hacve got to percolate up the restrict through all the program.
I don't think that's true (that is, I think at worst you'd have to
explicitly cast to 'restrict EMPLOYEE *' in the call, and I'm not sure
that's required either), but let it pass.
However do this

void employ(EMPLOYEE *employees, int N, EMPLOYEE *candidate)
{
if(memsame(employees, N * sizeof(EMPLOYEE), candidate, sizeof(EMPLOYEE))
{
/* something has gone deeply wrong if candidate already in our
list of employees. Debug code. */
assert(0);
}
/* compiler knows that at this point no alias */
/* call fast no-alias version of strcpy */
strcpy(emplyees[N-1].name, candidate->name);
}
There is no "fast no-alias version" of strcpy. The strcpy function
by definition /is/ "fast no-alias"; trying to strcpy overlapping objects
results in undefined behavior. Therefore, as I originally said, the
programmer is complicating and pessimizing his code by adding that
"memsame" call. The compiler certainly is not helped by it.
All you're doing is adding another assertion. Adding assertions may be
an admirable goal, but you could probably assert further up the call stack
for better effect.

Maybe if you post an example of code that would /benefit/ from this
new function, the advantages will become clearer.

-Arthur
Feb 10 '07 #8
Serve Laurijssen wrote:
Not sure about the use of such a function. aliasing is about compiletime
optimization. You want a compiler to generate code like:

if (alias(...))
{
// do "slow" code
}
else
{
// do "fast" code
}

not sure if that would speed things up :)
Also not sure if the programmer needs to even know about these kind of things.
A good implementation should do it on it's own.

Feb 10 '07 #9
"Malcolm McLean" <re*******@btinternet.comwrote:
# A proposed new function
#
# int alias(void *ptr1, size_t len1, void *ptr1, size_t len2)
#
# Returns true if the pointers overlap.
#
# On most machines it can be trivially implemented. However it has to be a
# standard library function because it is not necessarily legal to compare two
# address from different objects.

Wrong. It has to be in the standard if you want it implemented
everywhere. Gets in the standard if it can be implemented by all
committee members and they are sufficiently motivated.

It's legal on my machine to compare any two pointers. The standard
is not the only or ultimate authority. It is simply a common reference
point so that two people say they are using the same standard
(ANSI or ISO or CCITT or IFIP or POSIX or IEEE or cetera), then
they have communicated alot of information in a few words about
their expectations of what they can share.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
If you plan to shoplift, let us know.
Thanks
Feb 10 '07 #10
In article <12*************@corp.supernews.com>,
SM Ryan <wy*****@tango-sierra-oscar-foxtrot-tango.fake.orgwrote:
>It's legal on my machine to compare any two pointers.
If I produce a binary and you load it down onto your machine, then
will your machine execute it differently than my machine (assuming
the same architecture)?

I seem to be a bit fuzzy as to how one would write code that would
detect that it was running on *your* machine, rather than
someone else's machine. What about machines that you are leasing,
what happens on them? And on machines that you are renting? How about
shared hosting service -- the function is legal when it is executed
on behalf of an account you are paying for, but not legal for
other people?

What happens if some code on one of your machines attempts to do
something that -you- have defined as illegal?

It's your machine, and so of course it is your rules, your say as to
what is "legal" or not on -your- machine -- but doesn't it all get
pretty messy to keep your rules disentangled from the rules of the
various standards?
It seems to me that most of us are content with letting this
kind of thing be *implementation specific*, rather than having the
behaviour defined according to some ill-defined property rights...
--
Is there any thing whereof it may be said, See, this is new? It hath
been already of old time, which was before us. -- Ecclesiastes
Feb 11 '07 #11
2007-02-11 <eq**********@canopus.cc.umanitoba.ca>,
Walter Roberson wrote:
In article <12*************@corp.supernews.com>,
SM Ryan <wy*****@tango-sierra-oscar-foxtrot-tango.fake.orgwrote:
>>It's legal on my machine to compare any two pointers.
[snip strawman nonsense]
It seems to me that most of us are content with letting this
kind of thing be *implementation specific*, rather than having the
behaviour defined according to some ill-defined property rights...
This is a rather perverse way of interpreting his statement. It's much
more straightforward to say "my machine is an example of a class of
machines on which this operation is supported" (or, if you want to be
very pedantic, "my machine is an example of a class of machines on which
implementations which support this operation are naturally supported by
the underlying hardware" or even "my machine is one on which the only
implementations installed on it do support this operation") - making
a claim about his machine certainly does not imply that that claim is
true _because_ it is his machine.
Feb 11 '07 #12

"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrote
On Sat, 10 Feb 2007, Malcolm McLean wrote:
>void employ(EMPLOYEE *employees, int N, EMPLOYEE *candidate)
{
if(memsame(employees, N * sizeof(EMPLOYEE), candidate,
sizeof(EMPLOYEE))
{
/* something has gone deeply wrong if candidate already in our
list of employees. Debug code. */
assert(0);
}
/* compiler knows that at this point no alias */
/* call fast no-alias version of strcpy */
strcpy(emplyees[N-1].name, candidate->name);
}

There is no "fast no-alias version" of strcpy. The strcpy function
by definition /is/ "fast no-alias"; trying to strcpy overlapping objects
results in undefined behavior. Therefore, as I originally said, the
programmer is complicating and pessimizing his code by adding that
"memsame" call. The compiler certainly is not helped by it.
All you're doing is adding another assertion. Adding assertions may be
an admirable goal, but you could probably assert further up the call stack
for better effect.

Maybe if you post an example of code that would /benefit/ from this
new function, the advantages will become clearer.
If you want to be fussy about it, stcpy does have an implict restrict.

So try this real function I wrote the other day.

int rectangle(unsigned char *rgba, int width, int height, double x1, double
y1, double x2, double y2, unsigned char *col)
{

int i;
int ii;
double temp;
int offset;

if(x1 x2)
{
temp = x1;
x1 = x2;
x2 = temp;
}
if(y1 y2)
{
temp = y1;
y1 = y2;
y2 = temp;
}
if(x1 < 0)
x1 = 0;
if(x2 width - 1)
x2 = width-1;
if(y1 < 0)
y1 = 0;
if(y2 height - 1)
y2 = height -1;

for(i=(int)y1;i<= (int) y2; i++)
for(ii = (int) x1; ii<= (int) x2; ii++)
{
offset = (i * width + ii) * 4;
rgba[ offset ] = ((int) col[0] * col[3] + rgba[offset] * (255 -
col[3]))/255;
rgba[ offset + 1] = (((int) col[1]) * col[3] + rgba[offset+1] * (255 -
col[3])) / 255;
rgba[ offset + 2] = (((int) col[2]) * col[3] + rgba[offset+2] * (255 -
col[3])) / 255;
}

return 0;
}

Fortunately it is not a bottleneck function, but it could easily be. The
problem for the compiler is that col - the rectangle colour - could easily
be an alias for the draw space. So it has got to either take risks or read
the colour from memory on each pixel.
So add a "memsame" at the front of the function, and the compiler can
optimise the code.
Feb 11 '07 #13

"Malcolm McLean" <re*******@btinternet.comwrote in message
news:ab******************************@bt.com...
Fortunately it is not a bottleneck function, but it could easily be. The
problem for the compiler is that col - the rectangle colour - could easily
be an alias for the draw space. So it has got to either take risks or read
the colour from memory on each pixel.
So add a "memsame" at the front of the function, and the compiler can
optimise the code.
how exactly do you think the compiler can optimize things better by adding a
function call to your code?
restrict comes closer. If the function turns out to be a bottleneck you can
make another function with restricted pointers
Feb 11 '07 #14

"Serve Laurijssen" <se*@n.tkwrote in message news
>
"Malcolm McLean" <re*******@btinternet.comwrote in message
news:ab******************************@bt.com...
>Fortunately it is not a bottleneck function, but it could easily be. The
problem for the compiler is that col - the rectangle colour - could
easily be an alias for the draw space. So it has got to either take risks
or read the colour from memory on each pixel.
So add a "memsame" at the front of the function, and the compiler can
optimise the code.

how exactly do you think the compiler can optimize things better by adding
a function call to your code?
restrict comes closer. If the function turns out to be a bottleneck you
can make another function with restricted pointers
After a call to memsame() fails, the pointers have an implicit restrict.
So effectively what we are doing is binding the restrict at run time rather
than at ccompile time. It makes it more difficult for the compiler to
optimise, but the benefit is that you then don't have restrict poisoning
clogging up you whole call tree.

A naive compiler cannot use the information to optimise, but the function is
so cheap that it can be inlined with very low cost.
Feb 11 '07 #15
ro******@ibd.nrc-cnrc.gc.ca (Walter Roberson) wrote:

# I seem to be a bit fuzzy as to how one would write code that would
# detect that it was running on *your* machine, rather than

The genitive is not the same as the possessive. Learn to speaking
english good. If you are using a Macintosh OS 10.4, then you are
using my machine.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
You face forward, or you face the possibility of shock and damage.
Feb 11 '07 #16

"Malcolm McLean" <re*******@btinternet.comwrote in message
news:vu******************************@bt.com...
After a call to memsame() fails, the pointers have an implicit restrict.
So effectively what we are doing is binding the restrict at run time
rather than at ccompile time.
Can you give an example on how you envision that it should work in real
code?
Either I'm missing something here or it just isnt possible what you want.

A compiler cant optimize at runtime, or well C compilers cant :)
The only thing I can see how the function could work is like

void foo(char *p1, char *p2)
{
if (memsame(p1,p2))
memmove();
else
memcpy();
}

but then you provide the optimization which can be handled more gracefully
by

void foo(char *p1, char *p2) { memmove(); }
void kungfoo(char * restrict p1, char * restrict p2) { memcpy(); }

And the compiler also knows it can do the usual aliasing optimizations on
the restrict version.
I really dont see a use for such a function.
Feb 11 '07 #17

"Serve Laurijssen" <se*@n.tkwrote in message
>
"Malcolm McLean" <re*******@btinternet.comwrote in message
news:vu******************************@bt.com...
>After a call to memsame() fails, the pointers have an implicit restrict.
So effectively what we are doing is binding the restrict at run time
rather than at ccompile time.

Can you give an example on how you envision that it should work in real
code?
Either I'm missing something here or it just isnt possible what you want.

A compiler cant optimize at runtime, or well C compilers cant :)
The only thing I can see how the function could work is like

void foo(char *p1, char *p2)
{
if (memsame(p1,p2))
memmove();
else
memcpy();
}

That is exactly how it is. A modern memcpy() is probably written just like
that to allow aliases and efficinet copying of non-aliases. It can't be done
portably in A|NSI C, because of the pointers to different objects not
comparing rule.
but then you provide the optimization which can be handled more gracefully
by

void foo(char *p1, char *p2) { memmove(); }
void kungfoo(char * restrict p1, char * restrict p2) { memcpy(); }

And the compiler also knows it can do the usual aliasing optimizations on
the restrict version.
I really dont see a use for such a function.
The problem is we've got this.

high_level_function(MYTYPE *ptr1, MYTYPE *ptr2)
{
kungfoo(ptr1, ptr2);
}

sorry, says the compiler. Make that high_level_function(restrict MYTYPE
*ptr1, restrict MYTYPE *ptr2).

Then every caller of high_level_function must ensure that parameters are
restricted. However that can be hard to arrange. So the whole program grinds
up in a mass of difficulties.

This way, we go

high_level_function(MYTYPE *ptr1, MYTYPE *ptr2)
{
if(memsame(ptr1, sizeof *ptr1, ptr2, sizeof ptr2))
foo()
else
kungfoo();
}

So we are handling the problem at runtime rather than compile time, which
isn't in itself ideal, but it buys us an escape from restrict poisoning.

Feb 11 '07 #18
SM Ryan wrote:
ro******@ibd.nrc-cnrc.gc.ca (Walter Roberson) wrote:

# I seem to be a bit fuzzy as to how one would write code that would
# detect that it was running on *your* machine, rather than

The genitive is not the same as the possessive. Learn to speaking
english good. If you are using a Macintosh OS 10.4, then you are
using my machine.
Really - and our current use and allocation of dynamic memory is exactly the
same?
Feb 12 '07 #19
Malcolm McLean wrote:
>void foo(char *p1, char *p2)
{
if (memsame(p1,p2))
memmove();
else
memcpy();
}

That is exactly how it is. A modern memcpy() is probably written just like
that to allow aliases and efficinet copying of non-aliases. It can't be done
portably in A|NSI C, because of the pointers to different objects not
comparing rule.
google: opensolaris, memcpy.s
Feb 12 '07 #20
"Christopher Layne" <cl****@com.anodizedwrote in message
>
>That is exactly how it is. A modern memcpy() is probably written just
like
that to allow aliases and efficinet copying of non-aliases. It can't be
done
portably in A|NSI C, because of the pointers to different objects not
comparing rule.

google: opensolaris, memcpy.s
That one isn't. It will break if passed two buffers that overlap within the
same word.

That is legitimate, because memcpy() is defined as UB if passed aliased
types, but other memcpy()s, for instance the Iris one I used a while back
for RISC processors, do cut the user some slack on this and will handle
overlapping arguments, so memcpy() is effectively the same function as
memmove(). As a general rule that is the better approach, hence the
qualification, "modern" memcpy().


Feb 12 '07 #21

On Sun, 11 Feb 2007, Malcolm McLean wrote:
"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrote
>>
There is no "fast no-alias version" of strcpy. The strcpy function
by definition /is/ "fast no-alias"; trying to strcpy overlapping objects
results in undefined behavior. Therefore, as I originally said, the
programmer is complicating and pessimizing his code by adding that
"memsame" call. The compiler certainly is not helped by it.
All you're doing is adding another assertion. Adding assertions may be
an admirable goal, but you could probably assert further up the call stack
for better effect.

Maybe if you post an example of code that would /benefit/ from this
new function, the advantages will become clearer.
If you want to be fussy about it, stcpy does have an implict restrict.
No, if I wanted to be fussy, I'd ask what you meant by "stcpy".
So try this real function I wrote the other day.

int rectangle(unsigned char *rgba, int width, int height, double x1, double
y1, double x2, double y2, unsigned char *col)
{
[...]
for(i=(int)y1;i<= (int) y2; i++)
for(ii = (int) x1; ii<= (int) x2; ii++)
{
offset = (i * width + ii) * 4;
rgba[ offset ] = ((int) col[0] * col[3] + rgba[offset] * (255 -
col[3]))/255;
rgba[ offset + 1] = (((int) col[1]) * col[3] + rgba[offset+1] * (255 -
col[3])) / 255;
rgba[ offset + 2] = (((int) col[2]) * col[3] + rgba[offset+2] * (255 -
col[3])) / 255;
}

return 0;
}

Fortunately it is not a bottleneck function, but it could easily be. The
problem for the compiler is that col - the rectangle colour - could easily
be an alias for the draw space. So it has got to either take risks or read
the colour from memory on each pixel.
So add a "memsame" at the front of the function, and the compiler can
optimise the code.
Add 'restrict' at the front of each pointer variable, and the compiler
can optimize the code, without needing to use anything not already present
in the existing C99 standard.

'restrict' does not suffer from the "poisoning" problem ("const
poisoning"); there's no need to propagate it up the call chain.

If you're really paranoid about some halfway-conforming compiler
requiring you to cast 'restrict', you could always write

void im_scared(unsigned char *p, unsigned char *q) {
unsigned char * restrict real_p = p;
unsigned char * restrict real_q = q;
...and now deal with real_p and real_q...
}

But, as I said, that's not necessary in C99.

-Arthur
Feb 12 '07 #22

On Mon, 12 Feb 2007, Arthur J. O'Dwyer wrote:
>
'restrict' does not suffer from the "poisoning" problem ("const
poisoning"); there's no need to propagate it up the call chain.
...And by "up", I meant "down". (Brain fart.) I can't think of
anything that propagates /up/ the call chain in C.
(Except non-constness. ;)

If you're really paranoid about some halfway-conforming compiler
requiring you to cast 'restrict', you could always write

void im_scared(unsigned char *p, unsigned char *q) {
unsigned char * restrict real_p = p;
unsigned char * restrict real_q = q;
...and now deal with real_p and real_q...
}
However, that seems to be a pessimization on both compilers I tried
(GCC and Green Hills) --- you get worse code that way than if you'd
simply omitted 'restrict' in the first place. (GCC 3.3.5 seems to
ignore 'restrict' qualifiers anyway, as far as I can tell, so it
doesn't give you better code from any of these contortions.)

-Arthur
Feb 12 '07 #23

"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrote in message
On Mon, 12 Feb 2007, Arthur J. O'Dwyer wrote:
>>
'restrict' does not suffer from the "poisoning" problem ("const
poisoning"); there's no need to propagate it up the call chain.

...And by "up", I meant "down". (Brain fart.) I can't think of
anything that propagates /up/ the call chain in C.
(Except non-constness. ;)
That's the whole point.
restrict poisioning is like const poisoning, but much worse, because you
poison two variables at each stage.
Feb 12 '07 #24
Malcolm McLean wrote, On 12/02/07 10:31:
"Christopher Layne" <cl****@com.anodizedwrote in message
>>That is exactly how it is. A modern memcpy() is probably written just
like
that to allow aliases and efficinet copying of non-aliases. It can't be
done
portably in A|NSI C, because of the pointers to different objects not
comparing rule.
google: opensolaris, memcpy.s
That one isn't. It will break if passed two buffers that overlap within the
same word.
Ah, so a memcpy that does not meet your expectations is not a valid
counter-example to your expectations of how memcpy is written?
That is legitimate, because memcpy() is defined as UB if passed aliased
types, but other memcpy()s, for instance the Iris one I used a while back
for RISC processors, do cut the user some slack on this and will handle
overlapping arguments, so memcpy() is effectively the same function as
memmove(). As a general rule that is the better approach, hence the
qualification, "modern" memcpy().
As a general rule of thumb I will use memmove if there is is a
possibility of overlap (or if I'm being lazy) and memcpy if I want
efficiency so I would say that making memcpy as efficient as possible
and only having the overhead of the check in memmove is a better
approach as a general rule.

Both memcpy and memmove are provided for good reasons.
--
Flash Gordon
Feb 12 '07 #25

"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
>
As a general rule of thumb I will use memmove if there is is a possibility
of overlap (or if I'm being lazy) and memcpy if I want efficiency so I
would say that making memcpy as efficient as possible and only having the
overhead of the check in memmove is a better approach as a general rule.

Both memcpy and memmove are provided for good reasons.
It depends what the consequences are of you accidentally using a memcpy()
when you meant to use memmove(). If nothing too dire suggests itself, then
it is better to have that little bit extra efficiency and omit the check.
Feb 12 '07 #26
Malcolm McLean wrote, On 12/02/07 23:18:
"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
>As a general rule of thumb I will use memmove if there is is a possibility
of overlap (or if I'm being lazy) and memcpy if I want efficiency so I
would say that making memcpy as efficient as possible and only having the
overhead of the check in memmove is a better approach as a general rule.

Both memcpy and memmove are provided for good reasons.
It depends what the consequences are of you accidentally using a memcpy()
when you meant to use memmove(). If nothing too dire suggests itself, then
it is better to have that little bit extra efficiency and omit the check.
If you use the correct function for your parameters the program works,
if you use the wrong one all bets are off with the most likely results
(unless using the DS9K) being an incorrect result or a crash.

If you do
ptr = malloc(10000);
instead of
tmpptr = realloc(ptr,10000);
if (...

Then your program will probably crash. If you do
tmpptr = realloc(ptr,10000);
without knowing if ptr is initialised there is a fair chance your
program will crash at some point.

The difference is that if you are not comfortable you can use memcpy
correctly you always have the option of banning it from your code and
sticking to memmove. Personally I prefer to know where my pointers point
which makes it trivially easy to know if it is safe to use memcpy and I
would not trust software using either function from someone who did not
know is memcpy would be safe in any place where they used either
function. After all, if they don't know if it is possible for the
regions to overlap how can they know what behaviour they want if they
do? The required behaviour is not always that of memmove!
--
Flash Gordon
Feb 13 '07 #27
Flash Gordon wrote:
As a general rule of thumb I will use memmove if there is is a
possibility of overlap (or if I'm being lazy) and memcpy if I want
efficiency so I would say that making memcpy as efficient as possible
and only having the overhead of the check in memmove is a better
approach as a general rule.

Both memcpy and memmove are provided for good reasons.
Exactly!
Feb 13 '07 #28
Malcolm McLean wrote:
It depends what the consequences are of you accidentally using a memcpy()
when you meant to use memmove(). If nothing too dire suggests itself, then
it is better to have that little bit extra efficiency and omit the check.
This is part of the "have the library hand-hold the programmer" school of
thought. How about, verify you aren't going to overlap and use memcpy in that
case, or memmove if not?
Feb 13 '07 #29

On Mon, 12 Feb 2007, Malcolm McLean wrote:
"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrote in message
>On Mon, 12 Feb 2007, Arthur J. O'Dwyer wrote:
>>>
'restrict' does not suffer from the "poisoning" problem ("const
poisoning"); there's no need to propagate it up the call chain.

...And by "up", I meant "down". (Brain fart.) I can't think of
anything that propagates /up/ the call chain in C.
(Except non-constness. ;)

That's the whole point.
restrict poisioning is like const poisoning, but much worse, because you
poison two variables at each stage.
"restrict poisoning" does not exist. (I said that already, in the
post you quoted above.)

You are solving a non-problem because you do not understand C typing
rules.

-Arthur
Feb 13 '07 #30
"Malcolm McLean" <re*******@btinternet.comwrote:
"Christopher Layne" <cl****@com.anodizedwrote in message
That is exactly how it is. A modern memcpy() is probably written just like
that to allow aliases and efficinet copying of non-aliases. It can't be done
portably in A|NSI C, because of the pointers to different objects not
comparing rule.
google: opensolaris, memcpy.s

That one isn't. It will break if passed two buffers that overlap within the
same word.

That is legitimate, because memcpy() is defined as UB if passed aliased
types, but other memcpy()s, for instance the Iris one I used a while back
for RISC processors, do cut the user some slack on this and will handle
overlapping arguments, so memcpy() is effectively the same function as
memmove(). As a general rule that is the better approach,
Beg to differ. There is a reason why we have _both_ memcpy() and
memmove(). If you want the memmove() behaviour, use memmove(), and don't
expect the rest of us to use a slower, and therefore inferior (and yes,
in the case of these functions the difference rather easily _can_ be
significant), memcpy().

Richard
Feb 13 '07 #31

"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
"Malcolm McLean" <re*******@btinternet.comwrote:
>"Christopher Layne" <cl****@com.anodizedwrote in message
>
That is exactly how it is. A modern memcpy() is probably written just
like
that to allow aliases and efficinet copying of non-aliases. It can't
be done
portably in A|NSI C, because of the pointers to different objects not
comparing rule.

google: opensolaris, memcpy.s

That one isn't. It will break if passed two buffers that overlap within
the
same word.

That is legitimate, because memcpy() is defined as UB if passed aliased
types, but other memcpy()s, for instance the Iris one I used a while back
for RISC processors, do cut the user some slack on this and will handle
overlapping arguments, so memcpy() is effectively the same function as
memmove(). As a general rule that is the better approach,

Beg to differ. There is a reason why we have _both_ memcpy() and
memmove().
Engineering involves tradeoffs. People who make different decisions usually
have good reasons. As a general rule is is better to avoid bugs than speed
up code, but it is not a universal rule by all means.
>
If you want the memmove() behaviour, use memmove(), and don't
expect the rest of us to use a slower, and therefore inferior (and yes,
in the case of these functions the difference rather easily _can_ be
significant), memcpy().
The snag is that memmove() is called memmove. Psychology matters. If
memmove() were called memcpy() and memcpy() fast_memcpy(), then matters
would be different.

The implemetation of memcpy() is up to the library provider. Since the
behaviour is undefined (to be clear on this point, "undefined behviour"
means "behaviour which is not defined by the C standard", some people have
in the past thought it means behaviour which is in some physical or
metaphysical state indefinable), the function can take any action on being
passed overlapping regions. The most risky behaviour of all is to process
most inputs as the caller expects, and to corrupt small areas of memory for
a few inputs. However a lot of code doesn't matter much. If your results
aren't of any real importance, as in a video game, then it is silly to fuss
about how memcpy() behaves on bugged input. Simply tell the user the disk is
dirty and he needs to remove it from the machine, clean it, and restart. If
you are controlling a real F16 instead of a pretend one, users tend to get
more agitated if things go wrong.

As for speed, with modern pipelined architectures there might actually be no
penalty, or only a few instructions, because the non-overlapped branch can
be predicted. It is illegal to call the fucntion with the other branch,
after all.
Feb 13 '07 #32
Malcolm McLean wrote, On 13/02/07 20:58:
"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
>"Malcolm McLean" <re*******@btinternet.comwrote:
>>"Christopher Layne" <cl****@com.anodizedwrote in message
That is exactly how it is. A modern memcpy() is probably written just
like
that to allow aliases and efficinet copying of non-aliases. It can't
be done
portably in A|NSI C, because of the pointers to different objects not
comparing rule.
google: opensolaris, memcpy.s
That one isn't. It will break if passed two buffers that overlap within
the
same word.

That is legitimate, because memcpy() is defined as UB if passed aliased
types, but other memcpy()s, for instance the Iris one I used a while back
for RISC processors, do cut the user some slack on this and will handle
overlapping arguments, so memcpy() is effectively the same function as
memmove(). As a general rule that is the better approach,
Beg to differ. There is a reason why we have _both_ memcpy() and
memmove().
Engineering involves tradeoffs. People who make different decisions usually
have good reasons. As a general rule is is better to avoid bugs than speed
up code, but it is not a universal rule by all means.
Yes, and where they don't want the risk of memcpy being used incorrectly
the programming shop or project can ban its use and police it.
>If you want the memmove() behaviour, use memmove(), and don't
expect the rest of us to use a slower, and therefore inferior (and yes,
in the case of these functions the difference rather easily _can_ be
significant), memcpy().
The snag is that memmove() is called memmove. Psychology matters. If
memmove() were called memcpy() and memcpy() fast_memcpy(), then matters
would be different.
So does training, so ensure your programmers are properly trained.
The implemetation of memcpy() is up to the library provider. Since the
behaviour is undefined (to be clear on this point, "undefined behviour"
means "behaviour which is not defined by the C standard", some people have
in the past thought it means behaviour which is in some physical or
metaphysical state indefinable), the function can take any action on being
passed overlapping regions.
I know the implementation is allowed to degine the behaviour.
The most risky behaviour of all is to process
most inputs as the caller expects, and to corrupt small areas of memory for
a few inputs. However a lot of code doesn't matter much. If your results
aren't of any real importance, as in a video game, then it is silly to fuss
about how memcpy() behaves on bugged input. Simply tell the user the disk is
dirty and he needs to remove it from the machine, clean it, and restart. If
you are controlling a real F16 instead of a pretend one, users tend to get
more agitated if things go wrong.
If I was reviewing the code and the programmer could not either prove
the regions would never overlap or that it was valid that the regions
overlapped and it was handled properly I would reject it. Actually, I
would reject it at the design stage so it would not be coded.

By the way, some of the software I have worked on *is* in various
avionics systems and so is some that I have reviewed. Some other designs
I have reviewed are not in avionics because it was rejected at review,
although not for this specific reason.

In any case, where it is valid for the regions to overlap I still
believe that you the programmer should evaluate the correct way to
handle it not just assume that what memmove does is correct. If you just
assume that memmove (or your version of memcpy) will always do the right
thing then you will be caught out by the strange bugs that you think
making memcpy an alias for memmove will solve.
As for speed, with modern pipelined architectures there might actually be no
penalty, or only a few instructions, because the non-overlapped branch can
be predicted. It is illegal to call the fucntion with the other branch,
after all.
In that case you can always call memmove and leave those of us who know
when it is needed to call memcpy or memmove as appropriate.

I don't believe in premature optimisation, but I also don't believe in
needlessly doing things in a slow way either.
--
Flash Gordon
Feb 14 '07 #33
Flash Gordon wrote:
Malcolm McLean wrote, On 13/02/07 20:58:
>The snag is that memmove() is called memmove. Psychology matters. If
memmove() were called memcpy() and memcpy() fast_memcpy(), then matters
would be different.

So does training, so ensure your programmers are properly trained.
This.
In that case you can always call memmove and leave those of us who know
when it is needed to call memcpy or memmove as appropriate.

I don't believe in premature optimisation, but I also don't believe in
needlessly doing things in a slow way either.
And this, I feel are things, which once highly valued, seem to be less valued
these days. Quite sad. But hey, when they've reduced it down to a room full
of monkeys pumping out code from Microsoft Visual CodeCrapper 2007, then I'm
sure everyone will be quite proud at their newfound ambivalence.

Just tell me where I can get some of that soylent green on the cheap.
Feb 14 '07 #34

"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
>
So does training, so ensure your programmers are properly trained.
If you have a way of training programmers to never make mistakes, then of
course you needn't worry about design methodology, debugging, or any of the
other little irritations the rest of us face.
>
I don't believe in premature optimisation, but I also don't believe in
needlessly doing things in a slow way either.
We are talking about two comparisons and a jump. Admittedly this is
memcpy(). For any other function it would be a no-brainer. You might argue
that memcpy() is so low-level that we should make a special exception, at
least in the final production library.
Which aircraft do you make components for, by the way?
Feb 14 '07 #35
Malcolm McLean wrote, On 14/02/07 08:25:
"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
>So does training, so ensure your programmers are properly trained.
If you have a way of training programmers to never make mistakes, then of
course you needn't worry about design methodology, debugging, or any of the
other little irritations the rest of us face.
I don't, but I have also come across these things called "reviews" where
experienced people read the requirements/design/other documentation/code
in detail to find as many problems as possible. Spotting the use of
memcpy when memmove should be used is easy in a review and the
programmer will learn from having had it pointed out and being required
to correct it.
>I don't believe in premature optimisation, but I also don't believe in
needlessly doing things in a slow way either.
We are talking about two comparisons and a jump. Admittedly this is
memcpy(). For any other function it would be a no-brainer.
In some programs memcpy is called a lot on small blocks of memory for
good reasons.
You might argue
that memcpy() is so low-level that we should make a special exception, at
least in the final production library.
No, I am arguing that there is a function that does what you want to if
that is the functionality you want use it rather than saying that
another function should be changed to be identical.
Which aircraft do you make components for, by the way?
I have never made components for any aircraft, but I have written
software for systems in several. I could tell you which but then I would
have to kill you...

I left the industry a few years ago and now work on commercial software
instead.
--
Flash Gordon
Feb 14 '07 #36
"Malcolm McLean" <re*******@btinternet.comwrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
If you want the memmove() behaviour, use memmove(), and don't
expect the rest of us to use a slower, and therefore inferior (and yes,
in the case of these functions the difference rather easily _can_ be
significant), memcpy().
The snag is that memmove() is called memmove. Psychology matters. If
memmove() were called memcpy() and memcpy() fast_memcpy(), then matters
would be different.
Bollocks. If your amateur programmer can't be arsed to read his
documentation before using a function called memmove(), that's his
problem, not mine, not the Standard's. I want, and many people need, a
memmove() which DTRT, and TRT for us is _not_ to unnecessarily duplicate
what memcpy() already does perfectly well.

Richard
Feb 16 '07 #37

"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
"Malcolm McLean" <re*******@btinternet.comwrote:
>"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
>If you want the memmove() behaviour, use memmove(), and don't
expect the rest of us to use a slower, and therefore inferior (and yes,
in the case of these functions the difference rather easily _can_ be
significant), memcpy().
The snag is that memmove() is called memmove. Psychology matters. If
memmove() were called memcpy() and memcpy() fast_memcpy(), then matters
would be different.

Bollocks. If your amateur programmer can't be arsed to read his
documentation before using a function called memmove(), that's his
problem, not mine, not the Standard's. I want, and many people need, a
memmove() which DTRT, and TRT for us is _not_ to unnecessarily duplicate
what memcpy() already does perfectly well.
Psychology matters.
Feb 17 '07 #38

"Malcolm McLean" <re*******@btinternet.comwrote in message
news:KL*********************@bt.com...
>Bollocks. If your amateur programmer can't be arsed to read his
documentation before using a function called memmove(), that's his
problem, not mine, not the Standard's. I want, and many people need, a
memmove() which DTRT, and TRT for us is _not_ to unnecessarily duplicate
what memcpy() already does perfectly well.
Psychology matters.
say, you guys got stuck in the memcpy/memmove discussion. Can you give an
example without memcpy where memsame might have use?
Feb 17 '07 #39
Malcolm McLean wrote, On 17/02/07 15:29:
"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
>"Malcolm McLean" <re*******@btinternet.comwrote:
>>"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
If you want the memmove() behaviour, use memmove(), and don't
expect the rest of us to use a slower, and therefore inferior (and yes,
in the case of these functions the difference rather easily _can_ be
significant), memcpy().

The snag is that memmove() is called memmove. Psychology matters. If
memmove() were called memcpy() and memcpy() fast_memcpy(), then matters
would be different.
Bollocks. If your amateur programmer can't be arsed to read his
documentation before using a function called memmove(), that's his
problem, not mine, not the Standard's. I want, and many people need, a
memmove() which DTRT, and TRT for us is _not_ to unnecessarily duplicate
what memcpy() already does perfectly well.
Psychology matters.
Yes, so it would be better to implement the library in a way to make it
is likely as possible that a program will fail if it uses the library
incorrectly so the programmer learns to use it properly. Therefore
memcpy should be written so that at least some of the time it will
produce incorrect results if used when memmove is the correct function
to use, possibly with a debug version that will actually check and crash
the program if it is misused.

Training matters far more than psychology.
--
Flash Gordon
Feb 17 '07 #40
"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
Malcolm McLean wrote, On 17/02/07 15:29:
>"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
>>"Malcolm McLean" <re*******@btinternet.comwrote:

"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
If you want the memmove() behaviour, use memmove(), and don't
expect the rest of us to use a slower, and therefore inferior (and
yes,
in the case of these functions the difference rather easily _can_ be
significant), memcpy().
>
The snag is that memmove() is called memmove. Psychology matters. If
memmove() were called memcpy() and memcpy() fast_memcpy(), then matters
would be different.
Bollocks. If your amateur programmer can't be arsed to read his
documentation before using a function called memmove(), that's his
problem, not mine, not the Standard's. I want, and many people need, a
memmove() which DTRT, and TRT for us is _not_ to unnecessarily duplicate
what memcpy() already does perfectly well.
Psychology matters.

Yes, so it would be better to implement the library in a way to make it is
likely as possible that a program will fail if it uses the library
incorrectly so the programmer learns to use it properly. Therefore memcpy
should be written so that at least some of the time it will produce
incorrect results if used when memmove is the correct function to use,
possibly with a debug version that will actually check and crash the
program if it is misused.
Yes. Ideally in debug runs memcpy() would detect overlap and crash out,
whilst in production runs it would accept overlaps. We have the right to
alter the undefined behaviour of the function, but not to insist that every
other conforming compiler does likewise.
However it is such a low-level function that normal rules of design do not
necessarily apply.
>
Training matters far more than psychology.
Psychology is just as important. It is something that programmers often
forget, because they design languages with a machine's eye.
A recent case was that Microsoft introduced some new keywords into a
compiler. The double-underscore sequence is reserved for the implementation,
so the correct way was to make the keywords start with double underscores.
So that's what they did, and were indunated with complaints from programmers
who actually had to use the language.You can't read and write sequences of
punctuation for very long.

Therefore the underscores had to come out.

Similarly, it is no good trying to get people to call a function called
"memmove" when there is one called "memcpy" sitting there, even if it is
safer and in a mechanical sort of sense better.
Feb 18 '07 #41
"Malcolm McLean" <re*******@btinternet.comwrites:
A recent case was that Microsoft introduced some new keywords into a
compiler. The double-underscore sequence is reserved for the
implementation, so the correct way was to make the keywords start
with double underscores. So that's what they did,
They deserve some congratulations for Doing The Right Thing.
and were indunated with complaints from programmers who actually had
to use the language.You can't read and write sequences of
punctuation for very long.
Also the correct response.
Therefore the underscores had to come out.
They deserve condemnation for polluting the user's namespace.

IMnaaHO, they should have kept the underscores and added a new header,
so that by the action of

#include <newheader>

the programmer indicates acceptance of the

#define newkeyword __newkeyword

equivalences it provides; no use of non-standard new header, no
non-standard new keywords to interfere with the programmer's existing,
previously-valid code and cause it to mysteriously break.

I intend to take this approach with my comprehensive review and repair
of my employer's compilers' compliance (or lack thereof) this year.
Existing incursions into the user's namespace will be withdrawn from
the compiler (and headers and libraries) proper, and replaced with the
above technique. There are bound to be gotchas which I will find out
the hard way, but if anybody here has already tripped over them and
wants to share then I have no objection to finding out the easy way.

mlp
Feb 18 '07 #42

On Sat, 18 Feb 2007, Mark L Pappin wrote:
"Malcolm McLean" <re*******@btinternet.comwrites:
>>
A recent case was that Microsoft introduced some new keywords into a
compiler. The double-underscore sequence is reserved for the
implementation, so the correct way was to make the keywords start
with double underscores. So that's what they did,

They deserve some congratulations for Doing The Right Thing.
[...]
IMnaaHO, they should have kept the underscores and added a new header,
so that by the action of

#include <newheader>

the programmer indicates acceptance of the

#define newkeyword __newkeyword

equivalences it provides; no use of non-standard new header, no
non-standard new keywords to interfere with the programmer's existing,
previously-valid code and cause it to mysteriously break.
I agree that that is definitely the Right Thing. However, something
that might be more user-friendly, and is /almost/ as right, is the
following approach which I have seen used in the real world:

Make __newkeyword a new keyword, but then /pre-define/ "newkeyword"
as a macro for it. That is, make the compiler act (almost) as if
every program started by #including <newheader>. If a user's code
uses "newkeyword" as a variable name, then that user is forced to
add "-Unewkeyword" to the compile options, or (ickier but equivalent)
add "#undef newkeyword" to the relevant source files.

This approach sacrifices Standard-conformance, but optimizes for the
common case (that the user wants the new keywords) while still letting
him compile legacy code pretty much painlessly. Of course, it's only
appropriate when "the user wants the new keywords" /is/ the common
case --- for example, adding a "vector" datatype to a compiler for DSPs,
where most code is going to be using that keyword. You obviously
wouldn't use this approach to add a "byte" keyword.

-Arthur
Feb 18 '07 #43
Malcolm McLean said:

<snip>
Ideally in debug runs memcpy() would detect overlap and crash
out,
I have never understood this fascination that people have with program
crashes.
whilst in production runs it would accept overlaps.
If the program uses memcpy to copy regions that overlap, it is broken,
and 'ideally' (as you put it), such programs don't make it into
production.

<snip>
A recent case was that Microsoft introduced some new keywords into a
compiler. The double-underscore sequence is reserved for the
implementation, so the correct way was to make the keywords start with
double underscores. So that's what they did, and were indunated with
complaints from programmers who actually had to use the language.You
can't read and write sequences of punctuation for very long.
If they can't handle a couple of leading underscores, though, they have
no business being programmers.
Therefore the underscores had to come out.
No, the programmers had to be educated: "*Here* is the language spec,
*here* is our bunch of extensions, *here* is the internationally agreed
rule that explains what we've done, as you can see, we had no choice,
aren't we good, following standards for a change? Now be a good
programmer and eat up your underscores. They'll put hairs on your
chest."
Similarly, it is no good trying to get people to call a function
called "memmove" when there is one called "memcpy" sitting there, even
if it is safer and in a mechanical sort of sense better.
I manage to use memmove when I need it. I don't see why "people" can't
do it just as easily. Or are you saying people are stupid?

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Feb 18 '07 #44
"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrites:
On Sat, 18 Feb 2007, Mark L Pappin wrote:
[...]
>IMnaaHO, they should have kept the underscores and added a new header,
so that by the action of

#include <newheader>

the programmer indicates acceptance of the

#define newkeyword __newkeyword

equivalences it provides; no use of non-standard new header, no
non-standard new keywords to interfere with the programmer's existing,
previously-valid code and cause it to mysteriously break.

I agree that that is definitely the Right Thing. However, something
that might be more user-friendly, and is /almost/ as right, is the
following approach which I have seen used in the real world:

Make __newkeyword a new keyword, but then /pre-define/ "newkeyword"
as a macro for it. That is, make the compiler act (almost) as if
every program started by #including <newheader>. If a user's code
uses "newkeyword" as a variable name, then that user is forced to
add "-Unewkeyword" to the compile options, or (ickier but equivalent)
add "#undef newkeyword" to the relevant source files.

This approach sacrifices Standard-conformance, but optimizes for the
common case (that the user wants the new keywords) while still letting
him compile legacy code pretty much painlessly. Of course, it's only
appropriate when "the user wants the new keywords" /is/ the common
case --- for example, adding a "vector" datatype to a compiler for DSPs,
where most code is going to be using that keyword. You obviously
wouldn't use this approach to add a "byte" keyword.
There's another approach (already mentioned in this thread) that's
just as user-friendly *and* standard-compliant. Add "__newkeyword" as
a keyword, and add "#define newkeyword __newkeyword" in a new
<newfeature.hheader.

This is exactly what C99 did with the _Bool, _Complex, and _Imaginary
keywords.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 18 '07 #45
"Mark L Pappin" <ml*@acm.orgwrote in message
news:m3***************@Claudio.Messina...
"Malcolm McLean" <re*******@btinternet.comwrites:
>A recent case was that Microsoft introduced some new keywords into a
compiler. The double-underscore sequence is reserved for the
implementation, so the correct way was to make the keywords start
with double underscores. So that's what they did,

They deserve some congratulations for Doing The Right Thing.
>and were indunated with complaints from programmers who actually had
to use the language.You can't read and write sequences of
punctuation for very long.

Also the correct response.
>Therefore the underscores had to come out.
Out of curiosity, what was the compiler and what were the keywords?
The only case I know of in recent memory is managed VC++ with its
gcnew keyword.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Feb 18 '07 #46
Keith Thompson wrote:
"Arthur J. O'Dwyer" <aj*******@andrew.cmu.eduwrites:
On Sat, 18 Feb 2007, Mark L Pappin wrote:
[...]
IMnaaHO, they should have kept the underscores and added a new header,
so that by the action of

#include <newheader>

the programmer indicates acceptance of the

#define newkeyword __newkeyword

equivalences it provides; no use of non-standard new header, no
non-standard new keywords to interfere with the programmer's existing,
previously-valid code and cause it to mysteriously break.
I agree that that is definitely the Right Thing. However, something
that might be more user-friendly, and is /almost/ as right, is the
following approach which I have seen used in the real world:

Make __newkeyword a new keyword, but then /pre-define/ "newkeyword"
as a macro for it. That is, make the compiler act (almost) as if
every program started by #including <newheader>. If a user's code
uses "newkeyword" as a variable name, then that user is forced to
add "-Unewkeyword" to the compile options, or (ickier but equivalent)
add "#undef newkeyword" to the relevant source files.
<snip>
There's another approach (already mentioned in this thread) that's
just as user-friendly *and* standard-compliant. Add "__newkeyword" as
a keyword, and add "#define newkeyword __newkeyword" in a new
<newfeature.hheader.

This is exactly what C99 did with the _Bool, _Complex, and _Imaginary
keywords.
Or use a typedef in <newheader.h>

typedef __newkeyword newkeyword;

Feb 18 '07 #47
"santosh" <sa*********@gmail.comwrites:
Keith Thompson wrote:
[...]
>There's another approach (already mentioned in this thread) that's
just as user-friendly *and* standard-compliant. Add "__newkeyword" as
a keyword, and add "#define newkeyword __newkeyword" in a new
<newfeature.hheader.

This is exactly what C99 did with the _Bool, _Complex, and _Imaginary
keywords.

Or use a typedef in <newheader.h>

typedef __newkeyword newkeyword;
Only if __newkeyword is a type name.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 18 '07 #48
On Feb 14, 9:58 am, "Malcolm McLean" <regniz...@btinternet.comwrote:
The snag is that memmove() is called memmove. Psychology matters. If
memmove() were called memcpy() and memcpy() fast_memcpy(), then matters
would be different.
I thought "Zack"'s post about string termination was
a shoo-in for post of the week, then I read this..

Feb 18 '07 #49

"P.J. Plauger" <pj*@dinkumware.comwrote in message >>Therefore the
underscores had to come out.
>
Out of curiosity, what was the compiler and what were the keywords?
The only case I know of in recent memory is managed VC++ with its
gcnew keyword.
Did you ever wonder why the Managed Extensions have all those ugly underbar
keywords like __gc and __value? Because the Managed Extensions religiously
follow the C++ standard, which says, "If thou really must introduce new
keywords, thou shalt name them beginning with double underscore!" But guess
what? When Microsoft introduced __gc, __value and the rest, the
Redmondtonians received "unexpectedly strong" complaints from programmers.
Yeah! Programmers of the world, unite! You have nothing to lose but your
underbars. Underbars make your code look icky, like some kind of assembly
language program or something. So C++/CLI has ref and value, sans
underscores. This meant adding new keywords to C++, but so what? As Bjarne
says, "My experience is that people are addicted to keywords for introducing
concepts to the point where a concept that doesn't have its own keyword is
surprisingly hard to teach. This effect is more important and deep-rooted
than people's vocally expressed dislike for new keywords." (True, true. I
love that Bjarne is describing the psychology of programming.) So C++/CLI
ditched the underbars. By making them positional keywords instead of
reserved keywords, they can't conflict with programs that may already use
these words as variable or function names.

Full text:

http://msdn.microsoft.com/msdnmag/is...k/default.aspx
Feb 18 '07 #50

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: jcnews | last post by:
I am using Windows XP and am learning how to program in Java. Is there any way to get my fonts to be anti-aliased in both editors and in my programs? The non anti-aliased fonts don't look very...
10
by: Andy C | last post by:
Where can I get a python package to draw such figures? I googled and found PyX, I guess it outputs PostScript. I guess I can get a PostScript to BMP converter or something. Is there any other...
17
by: rgoya | last post by:
Peace be with you! About a year ago, I created a JavaScript which turns any web site into an online anti-war protest: http://www.geocities.com/rgoya/javascript/PROTEST.HTM I have recently...
6
by: Alan Kennedy | last post by:
Hi All, If there any contributors of SpamBayes reading, Congratulations! SpamBayes has won the Personal Computer World (pcw.co.uk) Editors Choice award for anti-spam software, in a review of...
1
by: ~~~ .NET Ed ~~~ | last post by:
Hi, Are there any known bad interactions between an ASP.NET (1.1)/IIS installation and the MS Windows Anti-spyware Beta? I have a working XP Pro with ASP.NET and don't want to let it go to hell....
0
by: Mark Rae | last post by:
Hi, Just a general question, really... Is anyone here using any of Microsoft's latest anti-virus / anti-spyware software?...
1
by: pete | last post by:
Hi, I have an application making a callout to McAfee anti-spam filter third-party library via Java JNI. The problem experienced is that after some amount of email is passed into the library it...
0
by: Treas4ever | last post by:
Hi, dudes. Do you use any anti wrinkle solutions? I've bought revitol anti aging, but don't know if it is safe or not. Maybe someone has used it? ----------------------------------...
16
by: lisa.engblom | last post by:
I have two semi related questions... First, I am trying to output a list of strings to a csv file using the csv module. The output file separates each letter of the string with a comma and then...
4
by: Mike | last post by:
Hi, I took an interest a few months ago in an anti framebreaker javascript. All my research told me that it was impossible. If a website is loaded into a frame/iframe then if it has frame...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.