Library bug or my fault?

193 views
Skip to first unread message

Steven Woody

unread,
Jul 22, 2008, 2:46:07 AM7/22/08
to
Hi,

Please check the sample code listed in the end of the message. It was
compiled using ARM/Linux cross-compiler and run on an ARM9 target. I
think the problem applies to this group because two cross-compiler
from different vendor result same error. So I guess it is not vendor
specific. If my guess is right, then it means the code itself may get
problem, but I can not figure out where it is.

The problem is, the line 38 which copy 3 bytes, starting from p2, to
p1, but the immediately followed memcmp (line 42) shows the memcpy was
not well done. I am sure the memcpy did not do the job, since if I
provide my own memcpy implemention as below, the error will go
disappear.

void memcpy(void *dest, void *src, size_t n)
{
uint8_t *d = (uint8_t*)dest;
uint8_t *s = (uint8_t*)src;

for (size_t i = 0; i < n; ++i)
*d++ = *s++;
}

Could you please check the code as well as the running result and
tell me what wrong with it? Thanks.


------------------------------------- the minimum sample
--------------------------------------------------
1 #include <stdio.h>
2 #include <string>
3 #include <stdint.h>
4 #include <assert.h>
5
6 struct Foo {
7 uint8_t x;
8 uint8_t y;
9 uint8_t z;
10 uint8_t m[3];
11 };
12
13 struct Bar
14 {
15 uint8_t m[3];
16 };
17
18 void pr(const char *title, const void *block, size_t n)
19 {
20 printf("%s\n", title);
21
22 uint8_t *p = (uint8_t*)block;
23 for (size_t i = 0; i < n; ++i)
24 printf("0x%02x ", *p++);
25
26 printf("\n");
27 }
28
29 void cp(const Foo *foo)
30 {
31 Bar bar;
32
33 Bar *p1 = &bar;
34 Bar *p2 = (Bar*)(foo->m);
35 pr("before: p1:", p1, 3);
36 pr("before: p2:", p2, 3);
37
38 memcpy(p1, p2, 3);
39 pr("after: p1:", p1, 3);
40 pr("after: p2:", p2, 3);
41
42 if (memcmp(p1, p2, 3) != 0)
43 printf("!!! cp is wrong\n");
44 }
45
46 int main()
47 {
48 Foo foo;
49 foo.x = 1;
50 foo.y = 2;
51 foo.z = 3;
52 foo.m[0] = 0x40;
53 foo.m[1] = 0x19;
54 foo.m[2] = 0x21;
55
56 cp(&foo);
57 cp2(&foo);
58 return 0;
59 }
------------------------------------------------------------------

Below is the running output on an ARM920T board:

before: p1:
0xfc 0x01 0x12
before: p2:
0x40 0x19 0x21
after: p1:
0x40 0x01 0x02
after: p2:
0x40 0x19 0x21
!!! cp is wrong

Peter Nilsson

unread,
Jul 22, 2008, 3:07:53 AM7/22/08
to
Steven Woody wrote:
> ...

> The problem is, the line 38 which copy 3 bytes, starting from
> p2, to p1, but the immediately followed memcmp (line 42)
> shows the memcpy was not well done.

It's the lines before that signal a problem.

> ------------------------------------- the minimum sample
> --------------------------------------------------
> 1 #include <stdio.h>
> 2 #include <string>
> 3 #include <stdint.h>
> 4 #include <assert.h>
> 5
> 6 struct Foo {
> 7 uint8_t x;
> 8 uint8_t y;
> 9 uint8_t z;
> 10 uint8_t m[3];
> 11 };
> 12
> 13 struct Bar
> 14 {
> 15 uint8_t m[3];
> 16 };

These are completely different structs.

> 29 void cp(const Foo *foo)
> 30 {
> 31 Bar bar;
> 32
> 33 Bar *p1 = &bar;
> 34 Bar *p2 = (Bar*)(foo->m);

The fact you have a cast to silence a warning (or more likely
error) on incompatible types is the problem. Bar is not an array,
it is a struct containing an array.

The standard allows the conversion (if foo->m is aligned
properly), but it says nothing more. Only if you convert it
back must it compare equal.

> 35 pr("before: p1:", p1, 3);
> 36 pr("before: p2:", p2, 3);
> 37
> 38 memcpy(p1, p2, 3);

If you really wanted to do this, then the following should work...

memcpy(bar->m, foo->m, sizeof foo->m);

If that fails, you have cuase for concern.

You have other options, like putting a Bar struct inside foo.
The you can use Bar pointers and simple assignment.

But fundamentally, you should be copying like to like.

<snip>

--
Peter

Ike Naar

unread,
Jul 22, 2008, 3:40:53 AM7/22/08
to
In article <be42888a-6b8d-49f1...@s50g2000hsb.googlegroups.com>,

Steven Woody <narke...@gmail.com> wrote:
>1 #include <stdio.h>
>2 #include <string>

That should be

#include <string.h>

You need <string.h> for the memcpy prototype.

Regards,
Ike

Martin Ambuhl

unread,
Jul 22, 2008, 4:07:25 AM7/22/08
to
Steven Woody wrote:
> Hi,
>
> Please check the sample code listed in the end of the message.

It seems to be written in some non-C but C-like language. Did you mean
to post to C++ instead? See if this version (notice the changes, more
may be advisable, but I address only what might be your problem) works
for you. There are clearly possible problems remaining (for example,
are you sure that accessing the uninitialized contents of 'bar' is safe?).

#include <stdio.h>
#include <string.h> /* mha: was 'string' */
#include <stdint.h>

struct Foo
{
uint8_t x;
uint8_t y;
uint8_t z;
uint8_t m[3];
};

struct Bar
{
uint8_t m[3];
};

void pr(const char *title, const void *block, size_t n)

{


printf("%s\n", title);

uint8_t *p = (uint8_t *) block;


for (size_t i = 0; i < n; ++i)

printf("0x%02x ", *p++);

printf("\n");
}

void cp(const struct Foo /* mha: added needed 'struct' */ *foo)
{
struct Bar bar; /* mha: added needed 'struct' here &
below */
struct Bar *p1 = &bar;
struct Bar *p2 = (struct Bar *) (foo->m);


pr("before: p1:", p1, 3);

pr("before: p2:", p2, 3);

memcpy(p1, p2, 3);


pr("after: p1:", p1, 3);

pr("after: p2:", p2, 3);

if (memcmp(p1, p2, 3) != 0)


printf("!!! cp is wrong\n");
}

int main()
{
struct Foo foo; /* mha: added need 'struct' */
foo.x = 1;
foo.y = 2;
foo.z = 3;
foo.m[0] = 0x40;
foo.m[1] = 0x19;
foo.m[2] = 0x21;

cp(&foo);
return 0;
}


before: p1:
0x20 0x20 0x20


before: p2:
0x40 0x19 0x21
after: p1:

0x40 0x19 0x21


after: p2:
0x40 0x19 0x21

Certainly the output is different from yours.

Steven Woody

unread,
Jul 22, 2008, 4:28:47 AM7/22/08
to
On Jul 22, 4:07 pm, Martin Ambuhl <mamb...@earthlink.net> wrote:
> Steven Woody wrote:
> > Hi,
>
> > Please check the sample code listed in the end of the message.
>
> It seems to be written in some non-C but C-like language. Did you mean
> to post to C++ instead? See if this version (notice the changes, more
> may be advisable, but I address only what might be your problem) works
> for you.

I am sorry, the #include <string> is a typo, and I should typedef
struct ... Foo/Bar to make it a pure C. Actually I did these in my
new version, but the problem keeps same.

> There are clearly possible problems remaining (for example,
> are you sure that accessing the uninitialized contents of 'bar' is safe?).

Why I cann't? I did not go beyond its boundary.

I copy/paste your version exactly, the output is totally same as whay
I posted previously. I guess you are running the code on a normal x86
PC. My original code also works on x86/Linux, it only appears when
run on ARM.

Nick Keighley

unread,
Jul 22, 2008, 4:29:32 AM7/22/08
to

post your code!!
You have no definition for cp2() so the code above won't compile.

I don't have a C99 compiler so I compiled this instead:
(can you miss out the "struct" keyword in C99?)

***************

#include <stdio.h>
/* #include <string> */ /* njk */
/* #include <stdint.h> */ /* njk */
#include <string.h> /* njk */
#include <assert.h>

typedef unsigned char uint8_t; /* njk */

struct Foo {
uint8_t x;
uint8_t y;
uint8_t z;
uint8_t m[3];
};

struct Bar
{
uint8_t m[3];
};

void pr(const char *title, const void *block, size_t n)
{
uint8_t *p = (uint8_t*)block; /* njk */
size_t i; /* njk */

printf("%s\n", title);

for (i = 0; i < n; ++i) /* njk */
printf("0x%02x ", *p++);

printf("\n");
}

void cp(const struct Foo *foo) /* njk */
{
struct Bar bar; /* njk */

struct Bar *p1 = &bar; /* njk */
struct Bar *p2 = (struct Bar*)(foo->m); /* njk */


pr("before: p1:", p1, 3);

pr("before: p2:", p2, 3);

memcpy(p1, p2, 3);


pr("after: p1:", p1, 3);

pr("after: p2:", p2, 3);

if (memcmp(p1, p2, 3) != 0)


printf("!!! cp is wrong\n");
}

int main()
{
struct Foo foo; /* njk */


foo.x = 1;
foo.y = 2;
foo.z = 3;
foo.m[0] = 0x40;
foo.m[1] = 0x19;
foo.m[2] = 0x21;

cp(&foo);
/* cp2(&foo); */ /* njk */
return 0;
}

***************

the lines I changes are marked /* njk */

This produced the following output

C:\bin\Debug>woody.exe
before: p1:
0x00 0x08 0x00


before: p2:
0x40 0x19 0x21
after: p1:

0x40 0x19 0x21


after: p2:
0x40 0x19 0x21

which looks ok to me


--
Nick Keighley

"Of course I'm going to be in an aeroplane on 31st December 1999.
You scientists wouldn't be stupid enough to build things that don't
work.
Besides what have computers got to do with aeroplanes anyway?"

Nick Keighley

unread,
Jul 22, 2008, 4:45:38 AM7/22/08
to
On 22 Jul, 08:07, Peter Nilsson <ai...@acay.com.au> wrote:
> Steven Woody wrote:

> > The problem is, the line 38 which copy 3 bytes, starting from
> > p2, to p1, but the immediately followed memcmp (line 42)
> > shows the memcpy was not well done.
>
> It's the lines before that signal a problem.
>
> > ------------------------------------- the minimum sample
> > --------------------------------------------------
> > 1 #include <stdio.h>
> > 2 #include <string>
> > 3 #include <stdint.h>
> > 4 #include <assert.h>
> > 5
> > 6 struct Foo {
> > 7     uint8_t x;
> > 8     uint8_t y;
> > 9     uint8_t z;
> > 10     uint8_t m[3];
> > 11 };
> > 12
> > 13 struct Bar
> > 14 {
> > 15     uint8_t m[3];
> > 16 };
>
> These are completely different structs.

yes, so?

> > 29 void cp(const Foo *foo)
> > 30 {
> > 31     Bar bar;
> > 32
> > 33     Bar *p1 = &bar;
> > 34     Bar *p2 = (Bar*)(foo->m);
>
> The fact you have a cast to silence a warning (or more likely
> error) on incompatible types is the problem. Bar is not an array,
> it is a struct containing an array.

yes, but there can't be padding at the beginning of a struct
hence Bar.m and Bar must be at the same address. Also
uint8_t is probably (almost certainly) an alias (typedef) for
unsigned char and you can safely cast *anything* to
unsigned char I'd say this pretty well had to work (do you
have a compiler where it doesn't work?)


> The standard allows the conversion (if foo->m is aligned
> properly),

why would foo->m not be correctly aligned? Suppose it was int
rather than uint8_t; I reckon it would *still* work (even on a
68000, which was the fussiest hardware I ever worked on)


> but it says nothing more. Only if you convert it
> back must it compare equal.

unless it's an unsigned char...


> > 35     pr("before: p1:", p1, 3);
> > 36     pr("before: p2:", p2, 3);
> > 37
> > 38     memcpy(p1, p2, 3);
>
> If you really wanted to do this, then the following should work...
>
>   memcpy(bar->m, foo->m, sizeof foo->m);
>
> If that fails, you have cuase for concern.

I think he has cause already

>
> You have other options, like putting a Bar struct inside foo.
> The you can use Bar pointers and simple assignment.
>
> But fundamentally, you should be copying like to like.

"up to a point, Lord Copper"


--
Nick Keighley

If cosmology reveals anything about God, it is that He has
an inordinate fondness for empty space and non-baryonic dark
matter.

Steven Woody

unread,
Jul 22, 2008, 4:52:17 AM7/22/08
to

Dear Peter,

Among all the replies, after real test, I found your fix is right. I
think your point is Foo::m is not Bar even though Bar is defined
exactly a structure contains merely Foo::m. This conflics with my
memory about the language. But, anyway, the result shows your are
absolutely right.

I am just wondering some things which still showing unreasonable:

1. In line 36 and line 40, why I can still use p2 to print the memory
without presenting a problem?
2. Why everything works normal when I substitue the memcpy with my
own implemention?
3. Why this won't happened on X86 but on ARM?

I hope get more opinions from your experts on the subject.

Thanks.

-
narke

Steven Woody

unread,
Jul 22, 2008, 5:03:35 AM7/22/08
to
>
> post your code!!
> You have no definition for cp2() so the code above won't compile.

Sorry. You just need to remove the line which invoke cp2(). It's not
important to the problem.

Your code works on x86 but not on ARM as I pointed out.

Steven Woody

unread,
Jul 22, 2008, 5:16:09 AM7/22/08
to
On Jul 22, 4:45 pm, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:

Yes, I thing every data elements here are aligned properly, since I
don't use any option such as #program pack() to bring in misalignment
problem. That's one thing I can not understand. If only one compiler
failed, I may believe that's the compiler's cause, but you see, two
different compiler from different vendor both failed in the same
place, this makes it looks not an conincident.

rahul

unread,
Jul 22, 2008, 6:42:23 AM7/22/08
to
On Tue, 22 Jul 2008 12:16:07 +0530, Steven Woody <narke...@gmail.com>
wrote:


> 35 pr("before: p1:", p1, 3);

Though printing garbage is not a constraint violation(p1 points to
uninitialized bar), isn't it better to initialize bar to something.

-- Posted on news://freenews.netfront.net - Complaints to ne...@netfront.net --

Martin Ambuhl

unread,
Jul 22, 2008, 7:04:54 AM7/22/08
to
Steven Woody wrote:
> On Jul 22, 4:07 pm, Martin Ambuhl <mamb...@earthlink.net> wrote:

>> There are clearly possible problems remaining (for example,
>> are you sure that accessing the uninitialized contents of 'bar' is safe?).
>
> Why I cann't? I did not go beyond its boundary.

Because of the possibility of bit patterns which don't correspond to
integral values (that's real).

> I copy/paste your version exactly, the output is totally same as whay
> I posted previously. I guess you are running the code on a normal x86
> PC. My original code also works on x86/Linux, it only appears when
> run on ARM.

Your compiler is broken, and in two ways:
1) My code should not misbehave with a non-broken C compiler and
2) Your code should not compile with a non-broken C compiler.

That your compiler compiles your code means that it is not a C compiler.
That your compiler gives erroneous results with my code means that it is
not a C compiler.

Nick Keighley

unread,
Jul 22, 2008, 7:52:35 AM7/22/08
to
you've lost some of the attributions

On 22 Jul, 10:03, Steven Woody <narkewo...@gmail.com> wrote:

> > post your code!!
> > You have no definition for cp2() so the code above won't compile.
>
> Sorry. You just need to remove the line which invoke cp2(). It's not
> important to the problem.

so you didn't post the ACTUAL code that exhibited the fault!

my code exhibts the bug?
very strange, you might actually have to debug it!

--
Nick Keighley

rahul

unread,
Jul 22, 2008, 8:04:09 AM7/22/08
to
On Tue, 22 Jul 2008 16:34:54 +0530, Martin Ambuhl <mam...@earthlink.net>
wrote:


> Because of the possibility of bit patterns which don't correspond to
> integral values (that's real).

I don't endorse accessing uninitialized variables. But what are bit
patterns which don't correspond to integral values? All you get is a
series of 1s and 0s and you will be getting some value. You don't care
about the value as you are deliberately using uninitialized variables.

Dik T. Winter

unread,
Jul 22, 2008, 8:13:38 AM7/22/08
to
In article <6829a2c4-748e-43e8...@e53g2000hsa.googlegroups.com> Nick Keighley <nick_keigh...@hotmail.com> writes:
> On 22 Jul, 10:03, Steven Woody <narkewo...@gmail.com> wrote:
...

Note the alignment problems I give below:

> > > struct Foo {
> > > uint8_t x;
> > > uint8_t y;
> > > uint8_t z;
> > > uint8_t m[3];
> > > };

A compiler can align 'm' any way it wants to, so it may start at any byte
address. And it can require stricter alignment of the struct itself.

> > > struct Bar
> > > {
> > > uint8_t m[3];
> > > };

A compiler is allowed to require stricter alignment rules for this struct.

> > > struct Bar bar; /* njk */

...


> > > struct Bar *p2 = (struct Bar*)(foo->m); /* njk */

This is a cast that does not necessariy work as you want because of alignment
differences.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

Richard Tobin

unread,
Jul 22, 2008, 8:40:42 AM7/22/08
to
In article <op.ueozs...@bugreplywarm-dx.eglbp.corp.yahoo.com>,
rahul <rahul...@gmai.com> wrote:

>> Because of the possibility of bit patterns which don't correspond to
>> integral values (that's real).

>I don't endorse accessing uninitialized variables. But what are bit
>patterns which don't correspond to integral values? All you get is a
>series of 1s and 0s and you will be getting some value. You don't care
>about the value as you are deliberately using uninitialized variables.

This is only a theoretical problem, not a practical one. It's
possible for an implementation to represent integers in such a way
that not all bit patterns are possible, but all modern general-purpose
computers use 2's complement arithmetic and use all the bits, so
it does not arise.

-- Richard

--
Please remember to mention me / in tapes you leave behind.

Dik T. Winter

unread,
Jul 22, 2008, 8:47:55 AM7/22/08
to
In article <EpSdnWbIepZFIxjV...@earthlink.com> Martin Ambuhl <mam...@earthlink.net> writes:
...

> Your compiler is broken, and in two ways:
> 1) My code should not misbehave with a non-broken C compiler and

In your code the line


struct Bar *p2 = (struct Bar *) (foo->m);

leads to undefined behaviour.

jacob navia

unread,
Jul 22, 2008, 9:00:26 AM7/22/08
to
rahul wrote:
> On Tue, 22 Jul 2008 16:34:54 +0530, Martin Ambuhl
> <mam...@earthlink.net> wrote:
>
>
>> Because of the possibility of bit patterns which don't correspond to
>> integral values (that's real).
> I don't endorse accessing uninitialized variables. But what are bit
> patterns which don't correspond to integral values?

They exist only on the minds of the regulars here...

> All you get is a
> series of 1s and 0s and you will be getting some value. You don't care
> about the value as you are deliberately using uninitialized variables.
>

You are applying logic in comp.lang.c. Note that for most regulars that
is an unknown concept.


--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32

jacob navia

unread,
Jul 22, 2008, 9:07:17 AM7/22/08
to
Martin Ambuhl wrote:
> Steven Woody wrote:
>> On Jul 22, 4:07 pm, Martin Ambuhl <mamb...@earthlink.net> wrote:
>
>>> There are clearly possible problems remaining (for example,
>>> are you sure that accessing the uninitialized contents of 'bar' is
>>> safe?).
>>
>> Why I cann't? I did not go beyond its boundary.
>
> Because of the possibility of bit patterns which don't correspond to
> integral values (that's real).
>

It is incredible how much nonsense can be posted in this group without
anyone commenting.

Mr Ambuhl is completely wrong. There isn't any single "bit pattern" that
can't be interpreted as an integer.

Proof:

Consider any bit pattern of any length. It is built from the alphabet:
{1,0}

Algorithm for finding the integer value:

1: Set the result to zero.
Set the bit counter to zero

2: Start at the right end of the number. [1]

3: If the bit at the current position is 1 add 2^counter
to the result.

4: Increment counter. If counter is less than the length of the bit
pattern go to step 3.

[1] What is the "right end" is not relevant. It is a matter of
convention. In all cases this algorithm does not depend on it
since it will equally yield an integer if we start at the "left"
end


>> I copy/paste your version exactly, the output is totally same as whay
>> I posted previously. I guess you are running the code on a normal x86
>> PC. My original code also works on x86/Linux, it only appears when
>> run on ARM.
>
> Your compiler is broken, and in two ways:
> 1) My code should not misbehave with a non-broken C compiler and
> 2) Your code should not compile with a non-broken C compiler.
>
> That your compiler compiles your code means that it is not a C compiler.
> That your compiler gives erroneous results with my code means that it is
> not a C compiler.
>

Richard Tobin

unread,
Jul 22, 2008, 9:23:37 AM7/22/08
to
In article <g64m3n$l38$1...@aioe.org>, jacob navia <ja...@nospam.org> wrote:

>> Because of the possibility of bit patterns which don't correspond to
>> integral values (that's real).

>Mr Ambuhl is completely wrong. There isn't any single "bit pattern" that


>can't be interpreted as an integer.

He didn't say it can't be interpreted as an integer. The issue is
whether it corresponds to an integer on the processor in question.
This is not a problem on any machine you're likely to encounter, but
it is a theoretical possibility.

Dik T. Winter

unread,
Jul 22, 2008, 9:45:47 AM7/22/08
to
In article <g64m3n$l38$1...@aioe.org> ja...@nospam.org writes:
...

> > Because of the possibility of bit patterns which don't correspond to
> > integral values (that's real).
>
> It is incredible how much nonsense can be posted in this group without
> anyone commenting.

Have a look wider than your narrow view. There are (or at least were)
computers where within a word some particular bit pattern corresponded
to a trap representation. 2-s complement with the range
[-int_max, int_max]
where the remaining pattern was a trap representation.

> Mr Ambuhl is completely wrong. There isn't any single "bit pattern" that
> can't be interpreted as an integer.

Of course that is true. But the question is not whether it *can* be
done, but whether the computer in fact *does* do it. And there are
computers that do not do it.

> 1: Set the result to zero.
> Set the bit counter to zero
>
> 2: Start at the right end of the number. [1]
>
> 3: If the bit at the current position is 1 add 2^counter
> to the result.
>
> 4: Increment counter. If counter is less than the length of the bit
> pattern go to step 3.
>
> [1] What is the "right end" is not relevant. It is a matter of
> convention. In all cases this algorithm does not depend on it
> since it will equally yield an integer if we start at the "left"
> end

Yes, for unsigned integers where each bit in the pattern represents a
value. Consider Honeywell machines (now Unisys, I think) with 72-bit
words where the first 8 bits or so are not value bits.

Chris Dollin

unread,
Jul 22, 2008, 10:09:45 AM7/22/08
to
jacob navia wrote:

> Mr Ambuhl is completely wrong. There isn't any single "bit pattern" that
> can't be interpreted as an integer.

That's true, but irrelevant; there are bit-patterns whose interpretation
as an integer isn't given by the algorithm you present, and other
bit-patterns that don't represent integers and so for which your
integer interpretation is meaningless.

--
'It changed the future .. and it changed us.' /Babylon 5/

Hewlett-Packard Limited registered office: Cain Road,
Bracknell,
registered no: 690597 England Berks RG12
1HN

jacob navia

unread,
Jul 22, 2008, 10:30:24 AM7/22/08
to
Chris Dollin wrote:
> jacob navia wrote:
>
>> Mr Ambuhl is completely wrong. There isn't any single "bit pattern" that
>> can't be interpreted as an integer.
>
> That's true, but irrelevant; there are bit-patterns whose interpretation
> as an integer isn't given by the algorithm you present, and other
> bit-patterns that don't represent integers and so for which your
> integer interpretation is meaningless.
>

If you would care to see the context of the discussion before
starting you would see that the discussion was about accessing
the bits of an uninitialized integer variable. In this context
it is obvious that even if the content of the variable is random
the value is an integer!

when I write

int aFunction(void)
{
int foo;
// Function start
}

At the comment point the value in "foo" is an integer.

jacob navia

unread,
Jul 22, 2008, 10:32:25 AM7/22/08
to
Dik T. Winter wrote:
> Yes, for unsigned integers where each bit in the pattern represents a
> value. Consider Honeywell machines (now Unisys, I think) with 72-bit
> words where the first 8 bits or so are not value bits.

Who cares about machines that do not exist since at least 10 years?
We are discussing a problem in a specific processor here, or at least
in current machines.

The regulars insist on their "trap representations" even if there
isn't a single machine today that uses this kind of crap.

Nick Keighley

unread,
Jul 22, 2008, 10:41:30 AM7/22/08
to

I have used a machine that had trap representations.
It was a 1's complement machine and therefore had a +0
and a -0. Reading a value that contained -0 caused a
trap to occur (I've no idea of the details but it
terminated your program).

<snip>


--
Nick Keighley

plan: an obsolete ICL 1900 series assembler language

jacob navia

unread,
Jul 22, 2008, 10:54:45 AM7/22/08
to
Nick Keighley wrote:
>
> I have used a machine that had trap representations.
> It was a 1's complement machine and therefore had a +0
> and a -0. Reading a value that contained -0 caused a
> trap to occur (I've no idea of the details but it
> terminated your program).
>
> <snip>
>
>
> --
> Nick Keighley
>
> plan: an obsolete ICL 1900 series assembler language

Can you maybe name an existing machine that shows this
kind of behavior?

Chris Dollin

unread,
Jul 22, 2008, 10:59:11 AM7/22/08
to
jacob navia wrote:

> Nick Keighley wrote:
>>
>> I have used a machine that had trap representations.
>> It was a 1's complement machine and therefore had a +0
>> and a -0. Reading a value that contained -0 caused a
>> trap to occur (I've no idea of the details but it
>> terminated your program).
>

> Can you maybe name an existing machine that shows this
> kind of behavior?

Can you promise that no future machine won't have this
kind of behaviour?

--
'It changed the future .. and it changed us.' /Babylon 5/

Hewlett-Packard Limited registered
no:
registered office: Cain Road, Bracknell, Berks RG12 1HN 690597
England

jacob navia

unread,
Jul 22, 2008, 11:01:25 AM7/22/08
to
Chris Dollin wrote:
> jacob navia wrote:
>
>> Nick Keighley wrote:
>>> I have used a machine that had trap representations.
>>> It was a 1's complement machine and therefore had a +0
>>> and a -0. Reading a value that contained -0 caused a
>>> trap to occur (I've no idea of the details but it
>>> terminated your program).
>> Can you maybe name an existing machine that shows this
>> kind of behavior?
>
> Can you promise that no future machine won't have this
> kind of behaviour?
>

Yes. If it disappeared there was a reason!

Chris Dollin

unread,
Jul 22, 2008, 11:16:12 AM7/22/08
to
jacob navia wrote:

> Chris Dollin wrote:
>> jacob navia wrote:
>>
>>> Mr Ambuhl is completely wrong. There isn't any single "bit pattern" that
>>> can't be interpreted as an integer.
>>
>> That's true, but irrelevant; there are bit-patterns whose interpretation
>> as an integer isn't given by the algorithm you present, and other
>> bit-patterns that don't represent integers and so for which your
>> integer interpretation is meaningless.
>>
>
> If you would care to see the context of the discussion before
> starting you would see that the discussion was about accessing
> the bits of an uninitialized integer variable.

Angels rush in where fools fear to tread! No, that's not right.
Oops.

> In this context
> it is obvious that even if the content of the variable is random
> the value is an integer!

Isn't that presupposing your conclusion?

> when I write
>
> int aFunction(void)
> {
> int foo;
> // Function start
> }
>
> At the comment point the value in "foo" is an integer.

At that point "foo" doesn't have a value, as you can tell
in the debugger, which interprets the tag bits for "foo"
as meaning "never set". Assignments to "foo" will set the
tag bits to "has been set", and leaving the scope of
"foo" will set them back to "never set" (or "unbound" or
whatever).

OK, I admit it: not only does your implementation not do this,
I don't have one that does either. But it's clear that an
implementation can -- legally -- do this, and that there are
plausible reasons for having an implementation that can.
(Implementations are, after all, not just the bare machine.)

So claiming that:

> At the comment point the value in "foo" is an integer.

assumes that it's legal to interpret "foo" as an integer
bit-pattern: but it isn't, whatever its bits are.

[1] Ha!

--
'It changed the future .. and it changed us.' /Babylon 5/

Hewlett-Packard Limited registered no:

jacob navia

unread,
Jul 22, 2008, 11:22:55 AM7/22/08
to
Chris Dollin wrote:
> OK, I admit it: not only does your implementation not do this,
> I don't have one that does either.

OK. We agree then. There are no implementations that
use some unspecified bits to see if a variable was initialized or not.


lcc-win (with optimization level zero) writes into all those variables
an integer value that is likely to trap if used as a pointer, and
is a NAN if used as a floating point number.

Those types DO have trap representations and accessing an invalid
pointer WILL get trapped by the hardware. I object to the integer
part of this.

Richard Heathfield

unread,
Jul 22, 2008, 11:34:53 AM7/22/08
to
jacob navia said:

> Chris Dollin wrote:
>> jacob navia wrote:
>>
>>> Nick Keighley wrote:
>>>> I have used a machine that had trap representations.
>>>> It was a 1's complement machine and therefore had a +0
>>>> and a -0. Reading a value that contained -0 caused a
>>>> trap to occur (I've no idea of the details but it
>>>> terminated your program).
>>> Can you maybe name an existing machine that shows this
>>> kind of behavior?
>>
>> Can you promise that no future machine won't have this
>> kind of behaviour?
>>
>
> Yes. If it disappeared there was a reason!

Such a promise is only worth anything if the person making it compensates
anyone and everyone who relies on that promise in the event that it turns
out to be false.

There are more machines in the world than the one sat on Jacob Navia's
desk, and more are being designed all the time. Machine designers who feel
tempted to use a design that incorporates trap representations will not
feel constrained by Jacob Navia's promise.

Furthermore, the fact that Nick Keighley bounced the question and, by
implication, doesn't know (or probably doesn't know) of any current
machines on which trap representations can occur - and for the record, I
don't know of any such machines either - does *not* imply that no such
current machines exist. Absence of evidence is not evidence of absence.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999

Richard Heathfield

unread,
Jul 22, 2008, 11:39:52 AM7/22/08
to
jacob navia said:

> Chris Dollin wrote:
>> OK, I admit it: not only does your implementation not do this,
>> I don't have one that does either.
>
> OK. We agree then.

Well, half-agree, anyway. You agree with your opinion, but he doesn't.

> There are no implementations that
> use some unspecified bits to see if a variable was initialized or not.

That's not what he said. He said he doesn't have such an implementation.
The fact that two, or three, or even a million people don't have pet
aardvarks does not imply that nobody has a pet aardvark. Furthermore, even
if it could somehow be shown that nobody has a pet aardvark today, that
doesn't imply that nobody will have a pet aardvark tomorrow.

<snip>

Ike Naar

unread,
Jul 22, 2008, 11:43:17 AM7/22/08
to
In article <g64lms$i40$1...@aioe.org>, jacob navia <ja...@nospam.org> wrote:
>rahul wrote:
>> On Tue, 22 Jul 2008 16:34:54 +0530, Martin Ambuhl
>> <mam...@earthlink.net> wrote:
>>> Because of the possibility of bit patterns which don't correspond to
>>> integral values (that's real).
>> I don't endorse accessing uninitialized variables. But what are bit
>> patterns which don't correspond to integral values?
>
>They exist only on the minds of the regulars here...

As an example, on the Burroughs B6700/7700/7900 (Unisys A series)
mainframe all numbers are represented in a floating point format
("real", in Burroughs jargon).
Integers are reals with a zero exponent.
As a consequence, a bit pattern that has any nonzero bit
in the exponent part is not an integral value.
An attempt to interpret such a pattern as an integral value
results in an 'invalid integer' trap.

Admittedly this is an old-fashioned architecture but it's not impossible
that such a machine is still in operation somewhere.

>> All you get is a
>> series of 1s and 0s and you will be getting some value. You don't care
>> about the value as you are deliberately using uninitialized variables.
>>
>You are applying logic in comp.lang.c. Note that for most regulars that
>is an unknown concept.

According to the stats you're in the top 10 list of frequent posters
in this group. Could that mean you are a regular yourself?
Just curious :-)

Ike

Richard

unread,
Jul 22, 2008, 11:45:16 AM7/22/08
to
Richard Heathfield <r...@see.sig.invalid> writes:

> jacob navia said:
>
>> Chris Dollin wrote:
>>> OK, I admit it: not only does your implementation not do this,
>>> I don't have one that does either.
>>
>> OK. We agree then.
>
> Well, half-agree, anyway. You agree with your opinion, but he doesn't.
>
>> There are no implementations that
>> use some unspecified bits to see if a variable was initialized or not.
>
> That's not what he said. He said he doesn't have such an implementation.
> The fact that two, or three, or even a million people don't have pet
> aardvarks does not imply that nobody has a pet aardvark. Furthermore, even
> if it could somehow be shown that nobody has a pet aardvark today, that
> doesn't imply that nobody will have a pet aardvark tomorrow.
>
> <snip>

But meanwhile in the real world where efficiency and cost effective SW development
is important ...

It's so nice to know that Heathfield's C link list library will run on
HW in 10,000,000 years time.

Walter Roberson

unread,
Jul 22, 2008, 11:51:02 AM7/22/08
to
In article <g64u23$26b$1...@aioe.org>, jacob navia <ja...@nospam.org> wrote:
>Chris Dollin wrote:
>> OK, I admit it: not only does your implementation not do this,
>> I don't have one that does either.

>OK. We agree then. There are no implementations that
>use some unspecified bits to see if a variable was initialized or not.

It's all somewhat fuzzy after these years, but if I recall correctly
I did use some very different systems with those properties a
few decades ago. I wasn't programming in C on them myself, but my
understanding is that the C implementations of the day did
respect those properties.
--
This is a Usenet signature block. Please do not quote it when replying
to one of my postings.
http://en.wikipedia.org/wiki/Signature_block

Walter Roberson

unread,
Jul 22, 2008, 12:08:05 PM7/22/08
to
In article <g64spo$op3$2...@aioe.org>, jacob navia <ja...@nospam.org> wrote:
>Chris Dollin wrote:
>> jacob navia wrote:

>>> Nick Keighley wrote:
>>>> I have used a machine that had trap representations.

>> Can you promise that no future machine won't have this
>> kind of behaviour?

>Yes. If it disappeared there was a reason!

Not necessarily a technical reason. See for example the history of
antitrust lawsuits against IBM in the 1970's (a time when technology
was settling down and what would move forward into the future was not
infrequently based upon anti-competitive economic grounds rather than
technical grounds.)
--
"To burn always with this hard, gem-like flame, to maintain this
ecstasy, is success in life." -- Walter Pater

Walter Roberson

unread,
Jul 22, 2008, 12:17:19 PM7/22/08
to
In article <g64r3c$gq8$2...@aioe.org>, jacob navia <ja...@nospam.org> wrote:
>Dik T. Winter wrote:
>> Yes, for unsigned integers where each bit in the pattern represents a
>> value. Consider Honeywell machines (now Unisys, I think) with 72-bit
>> words where the first 8 bits or so are not value bits.

>Who cares about machines that do not exist since at least 10 years?
>We are discussing a problem in a specific processor here, or at least
>in current machines.

A decade old doesn't mean "no productive use". My home and work
desktop machines are both from a line that went end-of-sale more
than a decade ago; there is still an active used market in the
model line. My work has more than once offered me an upgrade to
a MS Windows or Linux PC; I turn them down. With those old
systems I spend remarkably little time "fighting" the operating system
and hardware, because it was very well designed and integrated;
-every- DOS or Windows box I've had, I've had to spend more time
fixing the machine (hardware or software) than using the machine
productively.
--
"It is surprising what a man can do when he has to, and how
little most men will do when they don't have to."
-- Walter Linn

jacob navia

unread,
Jul 22, 2008, 12:19:18 PM7/22/08
to
Ike Naar wrote:
> In article <g64lms$i40$1...@aioe.org>, jacob navia <ja...@nospam.org> wrote:
>> rahul wrote:
>>> On Tue, 22 Jul 2008 16:34:54 +0530, Martin Ambuhl
>>> <mam...@earthlink.net> wrote:
>>>> Because of the possibility of bit patterns which don't correspond to
>>>> integral values (that's real).
>>> I don't endorse accessing uninitialized variables. But what are bit
>>> patterns which don't correspond to integral values?
>> They exist only on the minds of the regulars here...
>
> As an example, on the Burroughs B6700/7700/7900 (Unisys A series)
> mainframe all numbers are represented in a floating point format
> ("real", in Burroughs jargon).
> Integers are reals with a zero exponent.
> As a consequence, a bit pattern that has any nonzero bit
> in the exponent part is not an integral value.
> An attempt to interpret such a pattern as an integral value
> results in an 'invalid integer' trap.
>
> Admittedly this is an old-fashioned architecture but it's not impossible
> that such a machine is still in operation somewhere.
>

http://www.computermuseum.li/Testpage/Burroughs-6700-DP-System.htm
This is a system from the 1960s.

Yes, it is not IMPOSSIBLE that somewhere in the planet, there is still
some B6700 running around using floating point for integers... who
knows?

But since you can't point me to ANY such machine now, I strongly
suspect that when discussing problems in C programming TODAY we should
NOT confuse everyone with obsolete machines.

jacob navia

unread,
Jul 22, 2008, 12:24:55 PM7/22/08
to
Richard Heathfield wrote:
> jacob navia said:
>
>> Chris Dollin wrote:
>>> OK, I admit it: not only does your implementation not do this,
>>> I don't have one that does either.
>> OK. We agree then.
>
> Well, half-agree, anyway. You agree with your opinion, but he doesn't.
>

It would be nice if you spoke for yourself. I do not speak
for anyone else. Mr Dollin can say that for himeself

>> There are no implementations that
>> use some unspecified bits to see if a variable was initialized or not.
>
> That's not what he said. He said he doesn't have such an implementation.
> The fact that two, or three, or even a million people don't have pet
> aardvarks does not imply that nobody has a pet aardvark. Furthermore, even
> if it could somehow be shown that nobody has a pet aardvark today, that
> doesn't imply that nobody will have a pet aardvark tomorrow.
>

This rubbish is typical of your prose here.

heathfield:

"You have to cross your fingers always BEFORE and AFTER
you enter a house with an impair number in the door."

jacob:
Why? This look quite crazy.

heathfield:
You could be assaulted by the pet aardvarks if you don't!

jacob: What? Those do not exist!

heathfield:


> The fact that two, or three, or even a million people don't have pet
> aardvarks does not imply that nobody has a pet aardvark. Furthermore,
even
> if it could somehow be shown that nobody has a pet aardvark today, that
> doesn't imply that nobody will have a pet aardvark tomorrow.
>

THEREFORE:
cross your finger you dammed ignorant. Not all houses are like the
one you live in. There are some WEIRD houses where pet aardvarks loom.

This is pure C.L.C regulars nonsense.

Keith Thompson

unread,
Jul 22, 2008, 12:27:18 PM7/22/08
to
jacob navia <ja...@nospam.com> writes:
> Chris Dollin wrote:
>> jacob navia wrote:
>>> Nick Keighley wrote:
>>>> I have used a machine that had trap representations.
>>>> It was a 1's complement machine and therefore had a +0
>>>> and a -0. Reading a value that contained -0 caused a
>>>> trap to occur (I've no idea of the details but it
>>>> terminated your program).
>>> Can you maybe name an existing machine that shows this
>>> kind of behavior?
>> Can you promise that no future machine won't have this
>> kind of behaviour?
>
> Yes. If it disappeared there was a reason!

So if some future machine uses an integer representation with padding
bits, you will have broken your promise. Fascinating.

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

jacob navia

unread,
Jul 22, 2008, 12:29:08 PM7/22/08
to
Keith Thompson wrote:
> jacob navia <ja...@nospam.com> writes:
>> Chris Dollin wrote:
>>> jacob navia wrote:
>>>> Nick Keighley wrote:
>>>>> I have used a machine that had trap representations.
>>>>> It was a 1's complement machine and therefore had a +0
>>>>> and a -0. Reading a value that contained -0 caused a
>>>>> trap to occur (I've no idea of the details but it
>>>>> terminated your program).
>>>> Can you maybe name an existing machine that shows this
>>>> kind of behavior?
>>> Can you promise that no future machine won't have this
>>> kind of behaviour?
>> Yes. If it disappeared there was a reason!
>
> So if some future machine uses an integer representation with padding
> bits, you will have broken your promise. Fascinating.
>

Padding bits are masked by the hardware hence
they can't make a trap unless their value is
scanned by the hardware. But in that case they are not
padding bits.

I know that logic is not the strongest quality of C.L.C regulars
but... please try to follow the above even if it is difficult
ok?

Walter Roberson

unread,
Jul 22, 2008, 12:37:06 PM7/22/08
to
In article <lnbq0pk...@nuthaus.mib.org>,
Keith Thompson <ks...@mib.org> wrote:

>So if some future machine uses an integer representation with padding
>bits, you will have broken your promise. Fascinating.

I've heard of some DSPs using the floating point unit for integer
calculations -- saves die "real-estate", especially if integer
calculations are expected to be relatively rare compared to
whatever the DSP is optimized for. I do not, however, have enough
experience to know whether such systems sometimes store integers as a
subset of their floating point format or if they instead always
translate formats on the fly, completely transparently. I would
tend to expect that (copies of?) the values would be left in floating point
format in the floating point registers so as to reduce the overhead
of doing further calculation upon the results.
--
"There is nothing so bad but it can masquerade as moral."
-- Walter Lippmann

Ike Naar

unread,
Jul 22, 2008, 12:57:21 PM7/22/08
to
In article <g651bq$mus$1...@aioe.org>, jacob navia <ja...@nospam.org> wrote:
>http://www.computermuseum.li/Testpage/Burroughs-6700-DP-System.htm
>This is a system from the 1960s.

The B7900 and later Unisys A's are from the eighties.

>Yes, it is not IMPOSSIBLE that somewhere in the planet, there is still
>some B6700 running around using floating point for integers... who
>knows?
>
>But since you can't point me to ANY such machine now, I strongly
>suspect that when discussing problems in C programming TODAY we should
>NOT confuse everyone with obsolete machines.

My only point was to illustrate that machines, that you claimed only exist
"in the minds of the regulars" exist elsewhere too.

If I cannot point you to "ANY" such machine "TODAY", that does not mean
no such thing exists or will ever exist. In that respect my knowledge is
too limited.

Ike

Keith Thompson

unread,
Jul 22, 2008, 1:00:31 PM7/22/08
to
jacob navia <ja...@nospam.com> writes:
> Richard Heathfield wrote:
>> jacob navia said:
>>
>>> Chris Dollin wrote:
>>>> OK, I admit it: not only does your implementation not do this,
>>>> I don't have one that does either.
>>> OK. We agree then.
>> Well, half-agree, anyway. You agree with your opinion, but he
>> doesn't.
>>
>
> It would be nice if you spoke for yourself. I do not speak
> for anyone else. Mr Dollin can say that for himeself

You attempted to speak for Chris Dollin. You claimed that he agreed
with you, in the absence of any evidence that he actually does.

He said that *he doesn't have* such an implementation. You claimed
that he agreed with your assertion that *no such implementation
exists*.

Do you understand the difference?

For all I know, Chris might actually agree with you that no such
implementation exists, but he hasn't said so here; it's your claim in
the absence of any evidence that I object to.

[snip]

Keith Thompson

unread,
Jul 22, 2008, 1:18:41 PM7/22/08
to
jacob navia <ja...@nospam.com> writes:
> Keith Thompson wrote:
>> jacob navia <ja...@nospam.com> writes:
>>> Chris Dollin wrote:
>>>> jacob navia wrote:
>>>>> Nick Keighley wrote:
>>>>>> I have used a machine that had trap representations.
>>>>>> It was a 1's complement machine and therefore had a +0
>>>>>> and a -0. Reading a value that contained -0 caused a
>>>>>> trap to occur (I've no idea of the details but it
>>>>>> terminated your program).
>>>>> Can you maybe name an existing machine that shows this
>>>>> kind of behavior?
>>>> Can you promise that no future machine won't have this
>>>> kind of behaviour?
>>> Yes. If it disappeared there was a reason!
>> So if some future machine uses an integer representation with padding
>> bits, you will have broken your promise. Fascinating.
>
> Padding bits are masked by the hardware hence
> they can't make a trap unless their value is
> scanned by the hardware. But in that case they are not
> padding bits.

Do you claim that the above behavior is required for all possible
implementations, or is it merely an example of what you think *should*
be done. If it's merely an example, you could just as well have
asserted that there are no padding bits; that's an equally good
example.

> I know that logic is not the strongest quality of C.L.C regulars
> but... please try to follow the above even if it is difficult
> ok?

Ok. I've tried and failed to follow your argument. Are you arguing
that padding bits cannot exist?

Please re-read C99 6.2.6.2 regarding the representation of integer
types, just to make sure we're both talking about the same thing.
Perhaps you're using the phrase "padding bits" with a different
meaning that what's defined by the standard. If so, please clarify
what you mean, and please consider using a different term.

What exactly do you mean when you say that padding bits are "masked by
the hardware"?

Consider a hypothetical implementation with the following
characteristics:

CHAR_BIT == 8
sizeof(int) == 4 (32 bits)
INT_MIN == -8388608 (-2**23)
INT_MAX == +8388607 (+2**23-1)

Type int has 1 sign bit, 23 value bits, and 8 padding bits.

Storing the result of evaluating any arithmetic expression in an int
object causes the object's padding bits to be set to zero. (This can
be verified by interpreting the object's representation as an array of
unsigned char.) Evaluating the value of an object with non-zero
padding bits causes immediate termination of the program.

I know of no actual system that has the above characteristics; that's
not the point. I do not claim that such a system is likely to be
built in the future; that's not the point either (though there could
be legitimate reasons, reasons I haven't thought of, to build such a
system). The point is that such a system conforms to the C standard,
and there *could* be some future system that does exhibit the
characteristics I've described.

Do you agree? If so, doesn't that contradict your statement about
padding bits being "masked by the hardware"? If you don't agree, why
not?

I understand that you personally dislike the "regulars", of whom I am
one; as you wrote in another thread, "I am completely opposed to that
people". In replying to this, please try to get past your personal
animosity and respond to what I actually wrote.

Richard Heathfield

unread,
Jul 22, 2008, 2:36:47 PM7/22/08
to
jacob navia said:

> Richard Heathfield wrote:
>> jacob navia said:
>>
>>> Chris Dollin wrote:
>>>> OK, I admit it: not only does your implementation not do this,
>>>> I don't have one that does either.
>>> OK. We agree then.
>>
>> Well, half-agree, anyway. You agree with your opinion, but he doesn't.
>>
>
> It would be nice if you spoke for yourself.

I do so.

> I do not speak for anyone else.

Then why did you misrepresent Chris's position?

> Mr Dollin can say that for himeself

He did, but you tried to pretend he'd said something different.

>
>>> There are no implementations that
>>> use some unspecified bits to see if a variable was initialized or not.
>>
>> That's not what he said. He said he doesn't have such an implementation.
>> The fact that two, or three, or even a million people don't have pet
>> aardvarks does not imply that nobody has a pet aardvark. Furthermore,
>> even if it could somehow be shown that nobody has a pet aardvark today,
>> that doesn't imply that nobody will have a pet aardvark tomorrow.
>
> This rubbish is typical of your prose here.

Okay, so you don't understand it. Fine. And anything you don't understand,
you dismiss as rubbish, as I know only too well. So I'll try to explain it
in a completely different way.

The fact that two, or three, or even a million people don't have machines
that can have integer trap representations does not imply that nobody has
a machine that can have integer trap representations. Furthermore, even if
it could somehow be shown that nobody has a machine that can have integer
trap representations today, that doesn't imply that nobody will have a
machine that can have integer trap representations tomorrow.

Is that clearer? Or don't you understand that, either?

jacob navia

unread,
Jul 22, 2008, 2:46:34 PM7/22/08
to
Richard Heathfield wrote:
> The fact that two, or three, or even a million people don't have machines
> that can have integer trap representations does not imply that nobody has
> a machine that can have integer trap representations. Furthermore, even if
> it could somehow be shown that nobody has a machine that can have integer
> trap representations today, that doesn't imply that nobody will have a
> machine that can have integer trap representations tomorrow.
>
> Is that clearer? Or don't you understand that, either?
>

Of course I understand it:

"I can confuse everyone with bogus machines as long as I want to
because I do not need to have any relationship with reality. I can
*just invent* a possible machine with the characteristics I desire
so that I can go on confusing issues, making stupid assertions
about things that are legal or not, etc."

I understand it 100%. I just think that you are well, just
spraying nonsense (as most of the time)

Randy Howard

unread,
Jul 22, 2008, 2:55:58 PM7/22/08
to
On Tue, 22 Jul 2008 13:46:34 -0500, jacob navia wrote
(in article <g659vv$1e2$1...@aioe.org>):

> Richard Heathfield wrote:
>> The fact that two, or three, or even a million people don't have machines
>> that can have integer trap representations does not imply that nobody has
>> a machine that can have integer trap representations. Furthermore, even if
>> it could somehow be shown that nobody has a machine that can have integer
>> trap representations today, that doesn't imply that nobody will have a
>> machine that can have integer trap representations tomorrow.
>>
>> Is that clearer? Or don't you understand that, either?
>>
>
> Of course I understand it:
>
> "I can confuse everyone with bogus machines as long as I want to
> because I do not need to have any relationship with reality. I can
> *just invent* a possible machine with the characteristics I desire
> so that I can go on confusing issues, making stupid assertions
> about things that are legal or not, etc."
>
> I understand it 100%. I just think that you are well, just
> spraying nonsense (as most of the time)

Why do you spend so much time and energy trying to defend suspect code?
Is it just because you live and breathe for the chance to disagree
with "the evil regulars", or do you truly believe that analyzing the
contents of uninitialized variables is useful?


--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Richard Heathfield

unread,
Jul 22, 2008, 3:34:04 PM7/22/08
to
jacob navia said:

> Richard Heathfield wrote:
>> The fact that two, or three, or even a million people don't have
>> machines that can have integer trap representations does not imply that
>> nobody has a machine that can have integer trap representations.
>> Furthermore, even if it could somehow be shown that nobody has a machine
>> that can have integer trap representations today, that doesn't imply
>> that nobody will have a machine that can have integer trap
>> representations tomorrow.
>>
>> Is that clearer? Or don't you understand that, either?
>>
>
> Of course I understand it:

I think you don't understand it...

>
> "I can confuse everyone with bogus machines as long as I want to
> because I do not need to have any relationship with reality.

...and now I know you don't understand it.

Richard Heathfield

unread,
Jul 22, 2008, 3:34:33 PM7/22/08
to
Randy Howard said:

> On Tue, 22 Jul 2008 13:46:34 -0500, jacob navia wrote

<snip>

>> I understand it 100%. I just think that you are well, just
>> spraying nonsense (as most of the time)
>
> Why do you spend so much time and energy trying to defend suspect code?

Vendor lock-in.

dj3v...@csclub.uwaterloo.ca.invalid

unread,
Jul 22, 2008, 4:04:18 PM7/22/08
to
In article <g64vae$dev$1...@registered.motzarella.org>,
Richard <rgr...@gmail.com> wrote:

>But meanwhile in the real world where efficiency and cost effective SW
>development is important ...

...portability matters.

At my day job, we have both code written by standards-and-portability
weenies and code written by whatever-works types.

In terms of efficiency of the code, the standards-and-portability
weenies have a very slight advantage, since they fix their bugs
*before* the optimizer makes subtle bugs less subtle. But that's
barely noticeable at the best of times, and only a small amount of code
actually *needs* to run fast.

In terms of cost-effective development, any difference in productivity
between the standards-and-portability types and the whatever-works
types is completely lost in the effects of understanding of the problem
domain. (We have a lot of variability in the latter (in both the
problem domains and in who understands which ones how well), and it's
pretty much completely independent of the attitudes toward
portability.)


So for single-platform development, there's no detectable difference.
But now we're thinking of switching platforms.

The standards-and-portability weenies have already tested half the code
they've written on the platform we're thinking of switching to, since
that's what standards-and-portability weenies do. (Besides, some types
of problem are a lot easier to debug on that platform than on the one
we currently deploy on, so being able to run the code there already has
a nonnegative ROI.)
The whatever-works types have a whole bunch of code that has never been
compiled or run outside our current toolchain and deployment platform.

Which chunks of code do you think we're more likely to be able to get
running efficiently and cost-effectively on the new platform?


dave
(I don't expect Richard to provide any evidence of having gotten my
point, but it's worth pointing out for other readers.)

--
Dave Vandervies dj3vande at eskimo dot com
I have to go through 37 more source files of the original programmer.
He may well receive (posthumously) my thanks for making me a better
C programmer. --Nishad Prakash in comp.lang.c

jacob navia

unread,
Jul 22, 2008, 6:04:08 PM7/22/08
to
Keith Thompson wrote:
>
> Consider a hypothetical implementation with the following
> characteristics:
>
> CHAR_BIT == 8
> sizeof(int) == 4 (32 bits)
> INT_MIN == -8388608 (-2**23)
> INT_MAX == +8388607 (+2**23-1)
>
> Type int has 1 sign bit, 23 value bits, and 8 padding bits.
>
> Storing the result of evaluating any arithmetic expression in an int
> object causes the object's padding bits to be set to zero. (This can
> be verified by interpreting the object's representation as an array of
> unsigned char.) Evaluating the value of an object with non-zero
> padding bits causes immediate termination of the program.
>

Such a system is possible... if you do not care about
practical considerations...

> I know of no actual system that has the above characteristics; that's
> not the point. I do not claim that such a system is likely to be
> built in the future; that's not the point either (though there could
> be legitimate reasons, reasons I haven't thought of, to build such a
> system). The point is that such a system conforms to the C standard,
> and there *could* be some future system that does exhibit the
> characteristics I've described.
>

Yes. Something like that *could* exist.

> Do you agree?

Yes.

> If so, doesn't that contradict your statement about
> padding bits being "masked by the hardware"?

You are not talking about padding bits. You are talking about
control bits that are similar to the parity bits in serial
transmissions. Padding bits exist for alignment reasons.
Parity/control bits/redundancy bits are not there just to take
space, they have redundancy objectives.

> If you don't agree, why
> not?
>

See above

> I understand that you personally dislike the "regulars", of whom I am
> one; as you wrote in another thread, "I am completely opposed to that
> people". In replying to this, please try to get past your personal
> animosity and respond to what I actually wrote.
>


I did, but it was quite an effort. Anyway discussions are quite
useless. What bothers me here is that in discussions of people
that ask simple questions, regulars *invent* machines that
*could* exist just to confuse people.

They like (as all pedants) displaying their great "C knowledge",
by inventing possible situations where this or that paragraph of
the standard could apply.

As a matter of fact (of course) they are AGAINST the C99 standard
that they try to disqualify at each post. But they pose as
if they were for Standard C.

That is the AS IF rule!

Keith Thompson

unread,
Jul 22, 2008, 7:16:37 PM7/22/08
to
jacob navia <ja...@nospam.com> writes:
> Keith Thompson wrote:
>> Consider a hypothetical implementation with the following
>> characteristics:
>> CHAR_BIT == 8
>> sizeof(int) == 4 (32 bits)
>> INT_MIN == -8388608 (-2**23)
>> INT_MAX == +8388607 (+2**23-1)
>> Type int has 1 sign bit, 23 value bits, and 8 padding bits.
>> Storing the result of evaluating any arithmetic expression in an int
>> object causes the object's padding bits to be set to zero. (This can
>> be verified by interpreting the object's representation as an array of
>> unsigned char.) Evaluating the value of an object with non-zero
>> padding bits causes immediate termination of the program.
>
> Such a system is possible... if you do not care about
> practical considerations...

As a practical consideration, it's possible that some future system,
or perhaps some relatively exotic system that already exists that
neither of us happens to be familiar with, could have exactly the
characteristics I mentioned above, or something very similar.

I think I may actually have worked on a system that has padding bits
in some integer types. I didn't happen to do anything that was
affected by this, and I didn't check the values from <limits.h> while
I still had access to the system, so I can't be sure. The system was
a Cray T90; I'm fairly sure that it or some of its predecessors used
something like 24 out of 64 bits for some integer types. If I can get
access to a Cray again, I'll check it out.

The T90 is admittedly a fairly old system, and there are probably only
a few of them still in service. But they're not *that* old; the first
were shipped in 1995. And the reason for the odd behavior was a very
strong emphasis on floating-point over integer arithmetic, something
that could very well be a decisive factor for some future systems.

In any case, I actually find it *easier* in most cases to write code
that depends only on what's guaranteed by the standard.

>> I know of no actual system that has the above characteristics; that's
>> not the point. I do not claim that such a system is likely to be
>> built in the future; that's not the point either (though there could
>> be legitimate reasons, reasons I haven't thought of, to build such a
>> system). The point is that such a system conforms to the C standard,
>> and there *could* be some future system that does exhibit the
>> characteristics I've described.
>
> Yes. Something like that *could* exist.
>
>> Do you agree?
>
> Yes.

Excellent.

>> If so, doesn't that contradict your statement about
>> padding bits being "masked by the hardware"?
>
> You are not talking about padding bits. You are talking about
> control bits that are similar to the parity bits in serial
> transmissions. Padding bits exist for alignment reasons.
> Parity/control bits/redundancy bits are not there just to take
> space, they have redundancy objectives.

Yes, I certainly am talking about padding bits. I asked you to read
C99 6.2.6.2. Please read it again. It explains quite clearly what
padding bits are.

To be clear, parity bits that aren't visible to software are not
padding bits. Padding bits, as defined by the standard, exist only
for integer types; they're bits that are part of the type's
representation (and can therefore be seen if you view the type as an
array of unsigned char) but do not contribute to its value.

Padding *bytes* are used for alignment in structures; they're
mentioned in C99 6.2.6.1.

>> If you don't agree, why
>> not?
>
> See above
>
>> I understand that you personally dislike the "regulars", of whom I am
>> one; as you wrote in another thread, "I am completely opposed to that
>> people". In replying to this, please try to get past your personal
>> animosity and respond to what I actually wrote.
>
> I did, but it was quite an effort.

It should become easier with practice. Seriously.

> Anyway discussions are quite
> useless. What bothers me here is that in discussions of people
> that ask simple questions, regulars *invent* machines that
> *could* exist just to confuse people.

No, we invent machines that could exist to illustrate the wide variety
of machines that are possible, and to encourage programmers to think
about portability when they write code.

> They like (as all pedants) displaying their great "C knowledge",
> by inventing possible situations where this or that paragraph of
> the standard could apply.
>
> As a matter of fact (of course) they are AGAINST the C99 standard
> that they try to disqualify at each post. But they pose as
> if they were for Standard C.

I am not against the C99 standard. Where have I said that I am?

> That is the AS IF rule!

No, it isn't.

Richard Heathfield

unread,
Jul 22, 2008, 9:36:50 PM7/22/08
to
jacob navia said:

> Keith Thompson wrote:
>>
>> Consider a hypothetical implementation with the following
>> characteristics:
>>
>> CHAR_BIT == 8
>> sizeof(int) == 4 (32 bits)
>> INT_MIN == -8388608 (-2**23)
>> INT_MAX == +8388607 (+2**23-1)
>>
>> Type int has 1 sign bit, 23 value bits, and 8 padding bits.
>>
>> Storing the result of evaluating any arithmetic expression in an int
>> object causes the object's padding bits to be set to zero. (This can
>> be verified by interpreting the object's representation as an array of
>> unsigned char.) Evaluating the value of an object with non-zero
>> padding bits causes immediate termination of the program.
>>
>
> Such a system is possible... if you do not care about
> practical considerations...

I certainly hope that nobody would ever design such a system by choice, so
presumably such a system would only ever be designed *because* of
practical considerations.

Oops, I nearly gave another picturesque analogy. A good one, too. But
what's the point?

<snip>

Peter Nilsson

unread,
Jul 22, 2008, 9:32:28 PM7/22/08
to
Nick Keighley wrote:
> Peter Nilsson <ai...@acay.com.au> wrote:
> > Steven Woody wrote:
> > > The problem is, the line 38 which copy 3 bytes, starting from
> > > p2, to p1, but the immediately followed memcmp (line 42)
> > > shows the memcpy was not well done.
> >
> > It's the lines before that signal a problem.
> >
> > > ------------------------------------- the minimum sample
> > > --------------------------------------------------
> > > 1 #include <stdio.h>
> > > 2 #include <string>
> > > 3 #include <stdint.h>
> > > 4 #include <assert.h>
> > > 5
> > > 6 struct Foo {
> > > 7 � � uint8_t x;
> > > 8 � � uint8_t y;
> > > 9 � � uint8_t z;
> > > 10 � � uint8_t m[3];
> > > 11 };
> > > 12
> > > 13 struct Bar
> > > 14 {
> > > 15 � � uint8_t m[3];
> > > 16 };
> >
> > These are completely different structs.
>
> yes, so?

So conversion of an address of one (not the first) struct member
into a pointer to another struct is already suspicious.

> > > 29 void cp(const Foo *foo)
> > > 30 {
> > > 31 � � Bar bar;
> > > 32
> > > 33 � � Bar *p1 = &bar;
> > > 34 � � Bar *p2 = (Bar*)(foo->m);
> >
> > The fact you have a cast to silence a warning (or more likely
> > error) on incompatible types is the problem. Bar is not an array,
> > it is a struct containing an array.
>
> yes, but there can't be padding at the beginning of a struct

Irrelevant. The m being copied is in the middle of a Foo. Given
that it isn't a Bar, why should a pointer to that be portably
convertable to a pointer to Bar?

> hence Bar.m and Bar must be at the same address.

As my suggestion went on to show, there is clearly no problem
copying an array to an array of the same type and size directly.
But for no obvious reason, the code avoids that simple course.

> Also uint8_t is probably (almost certainly) an alias (typedef)
> for unsigned char and you can safely cast *anything* to
> unsigned char

Again, irrelevant. There is no conversion to unsigned char
anywhere in the code quoted above.

> I'd say this pretty well had to work (do you have a compiler where
> it doesn't work?)

The OP has a compiler where the code doesn't work. I don't know
why the compiler's doing what it's doing, I merely know that, on the
basis of what's been posted, neither the compiler nor the library
can be said to be at fault.

> > The standard allows the conversion (if foo->m is aligned
> > properly),
>
> why would foo->m not be correctly aligned?

Because any struct can have alignment requirements that are stricter
than the elements it contains.

Can you state any reasons why an implementation couldn't pad
a 3 byte structure to 4 bytes size and alignment?

--
Peter

Barry Schwarz

unread,
Jul 23, 2008, 1:22:07 AM7/23/08
to
On Mon, 21 Jul 2008 23:46:07 -0700 (PDT), Steven Woody
<narke...@gmail.com> wrote:

>Hi,
>
>Please check the sample code listed in the end of the message. It was
>compiled using ARM/Linux cross-compiler and run on an ARM9 target. I
>think the problem applies to this group because two cross-compiler
>from different vendor result same error. So I guess it is not vendor
>specific. If my guess is right, then it means the code itself may get
>problem, but I can not figure out where it is.


>
>The problem is, the line 38 which copy 3 bytes, starting from p2, to
>p1, but the immediately followed memcmp (line 42) shows the memcpy was

>not well done. I am sure the memcpy did not do the job, since if I
>provide my own memcpy implemention as below, the error will go
>disappear.
>
>void memcpy(void *dest, void *src, size_t n)
>{
> uint8_t *d = (uint8_t*)dest;

Why do you have a cast here?

> uint8_t *s = (uint8_t*)src;
>
> for (size_t i = 0; i < n; ++i)

What is the guarantee that n is never larger that sizeof(uint8_t)?

> *d++ = *s++;
>}
>
>Could you please check the code as well as the running result and
>tell me what wrong with it? Thanks.


>
>
>------------------------------------- the minimum sample
>--------------------------------------------------
>1 #include <stdio.h>
>2 #include <string>

You need to post your real code using cut and paste. Retyping just
introduces other errors confusing everyone.

>3 #include <stdint.h>
>4 #include <assert.h>
>5
>6 struct Foo {
>7 uint8_t x;
>8 uint8_t y;
>9 uint8_t z;
>10 uint8_t m[3];
>11 };
>12
>13 struct Bar
>14 {
>15 uint8_t m[3];
>16 };

>17
>18 void pr(const char *title, const void *block, size_t n)
>19 {
>20 printf("%s\n", title);
>21
>22 uint8_t *p = (uint8_t*)block;

This cast removes the const attribute. You should add it back by
fixing the definition of p. Otherwise, there is no point in having in
the function definition at all.

>23 for (size_t i = 0; i < n; ++i)
>24 printf("0x%02x ", *p++);
>25
>26 printf("\n");
>27 }
>28


>29 void cp(const Foo *foo)
>30 {
>31 Bar bar;
>32
>33 Bar *p1 = &bar;
>34 Bar *p2 = (Bar*)(foo->m);

>35 pr("before: p1:", p1, 3);
>36 pr("before: p2:", p2, 3);
>37
>38 memcpy(p1, p2, 3);
>39 pr("after: p1:", p1, 3);
>40 pr("after: p2:", p2, 3);
>41
>42 if (memcmp(p1, p2, 3) != 0)
>43 printf("!!! cp is wrong\n");

After making the obvious tweaks for C89, the code ran exactly as
expected on my system and never printed this message. By any chance
does your actual code have a ; after the if?

>44 }
>45
>46 int main()
>47 {
>48 Foo foo;
>49 foo.x = 1;
>50 foo.y = 2;
>51 foo.z = 3;
>52 foo.m[0] = 0x40;
>53 foo.m[1] = 0x19;
>54 foo.m[2] = 0x21;
>55
>56 cp(&foo);
>57 cp2(&foo);
>58 return 0;
>59 }
>------------------------------------------------------------------
>
>Below is the running output on an ARM920T board:
>
>before: p1:
>0xfc 0x01 0x12
>before: p2:
>0x40 0x19 0x21
>after: p1:
>0x40 0x01 0x02
>after: p2:
>0x40 0x19 0x21
>!!! cp is wrong


Remove del for email

Chris Torek

unread,
Jul 23, 2008, 5:23:25 AM7/23/08
to
There has been quite a lot of noise in this thread, but Dik Winter
has, I believe, identified the actual problem:

[I am not sure why the quote marks do not match up as I think the
authors here are correct]
>> On 22 Jul, 10:03, Steven Woody <narkewo...@gmail.com> wrote:
>>>> struct Foo {
>>>> uint8_t x;
>>>> uint8_t y;
>>>> uint8_t z;
>>>> uint8_t m[3];
>>>> };

In article <K4Epy...@cwi.nl> Dik T. Winter <Dik.W...@cwi.nl> wrote:
>A compiler can align 'm' any way it wants to, so it may start at any byte
>address. And it can require stricter alignment of the struct itself.

Right.

>>>> struct Bar
>>>> {
>>>> uint8_t m[3];
>>>> };

>A compiler is allowed to require stricter alignment rules for this struct.

Likewise ... and in this case, it does.

Now we hit the interesting bits:

>>>> struct Bar bar;
>>>> struct Bar *p2 = (struct Bar*)(foo->m);

>This is a cast that does not necessarily work as you want because
>of alignment differences.

The cast happens to work on the ARM, producing a pointer that is
"one byte away" from correct alignment. This would not (and does
not) matter to the compiler in some cases, but...

The next bit of code (which has been snipped here) does a memcpy(),
in effect doing:

memcpy(&bar, p2, 3);

The compiler is allowed to assume that p2 (which can only correctly
point to an actual instance of a "struct Bar") is 4-byte aligned,
and hence emit a "fast and inline" memcpy that does:

load two bytes from address given by p2
store two bytes to first two bytes of "bar"
load third byte from address given by p2+2
store third byte to third byte of "bar"

Here is where things get interesting. On the ARM, if you supply an
unaligned address to a load or store instruction that is loading or
storing more than one byte, the machine IGNORES THE LOW ORDER BITS.
In effect, this "means":

*(short *)&bar = *(short *)((uintptr_t)p2 & ~1);
*((char *)&bar + 2) = *((char *)p2 + 2);

Since p2 has the low order bit set, the hardware's "& ~1" (clear
low bit) has the effect of subtracting 1. So bar.m[0] will actually
take on the value of foo->z and bar.m[1] will take on the value of
foo->m[0], while bar.m[2] will take on the value of foo->m[2].

The lesson here is the same as always: "If you lie to the compiler,
it will get its revenge."
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html

Dik T. Winter

unread,
Jul 23, 2008, 8:30:28 AM7/23/08
to
In article <lnvdyxi...@nuthaus.mib.org> Keith Thompson <ks...@mib.org> writes:
...

> I think I may actually have worked on a system that has padding bits
> in some integer types. I didn't happen to do anything that was
> affected by this, and I didn't check the values from <limits.h> while
> I still had access to the system, so I can't be sure. The system was
> a Cray T90; I'm fairly sure that it or some of its predecessors used
> something like 24 out of 64 bits for some integer types. If I can get
> access to a Cray again, I'll check it out.

24 bits was used for 'short' and as a compiler option for 'int'. But
'int' itself was only 48 bits out of 64. And if the upper 16 bits were
not all zero you could get a big surprise when multiplying such things.

(When not all 16 bits of both operands were zero the multiplying unit
would assume that the operands were floating point and operate
accordingly.)
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

Keith Thompson

unread,
Jul 23, 2008, 11:15:14 AM7/23/08