64 bit Endianness issue

S

sureshjayaram

I have problem with the code only with 64 bit big endian machine.
i have a member size_t val1 in my structure. The size of size_t is
32(unsigned int) in 32 bit machines and 64(unsigned long) in 64 bit
machines.

I am passing address of this variable to a different function (where it
accepts only pointer to unsigned int) unsigned int *. Basically passing
a unsigned long pointer instead of unsigned int pointer. I think the
value is getting truncated while dereferencing int *. In this case how
do I make my code portable? Can functions like htonl/ntohl will help?
or casting could be of any help?

Thanks,
Suresh
 
W

Walter Roberson

I have problem with the code only with 64 bit big endian machine.
i have a member size_t val1 in my structure. The size of size_t is
32(unsigned int) in 32 bit machines and 64(unsigned long) in 64 bit
machines.
I am passing address of this variable to a different function (where it
accepts only pointer to unsigned int) unsigned int *. Basically passing
a unsigned long pointer instead of unsigned int pointer. I think the
value is getting truncated while dereferencing int *. In this case how
do I make my code portable?

On the 64 bit machines, can the values to be stored in the structure
member legitimately exceed 32 bits? If they can, then chances
are your only choice is to rewrite the other function. There is
nothing you can do to "remotely" force another routine to operate on
more bits than it was coded for.
 
C

Charles Mills

I have problem with the code only with 64 bit big endian machine.
i have a member size_t val1 in my structure. The size of size_t is
32(unsigned int) in 32 bit machines and 64(unsigned long) in 64 bit
machines.

I am passing address of this variable to a different function (where it
accepts only pointer to unsigned int) unsigned int *. Basically passing
a unsigned long pointer instead of unsigned int pointer. I think the
value is getting truncated while dereferencing int *. In this case how
do I make my code portable? Can functions like htonl/ntohl will help?
or casting could be of any help?

Thanks,
Suresh

Do the circumstances allow the following?

struct {
size_t val1;
} my_struct;
int tmp = 0;
some_function_that_takes_a_pointer_to_an_int(&tmp);
if (tmp < 0) /* do something */ ;
my_struct.val1 = tmp;

I assume some_function_that_takes_a_pointer_to_an_int() will be
dereferencing the pointer passed to it later. In this case you still
have some options, but it depends on how you are going to be using the
structure.

Charlie
 
S

sureshjayaram

It's like..

struct {
size_t val1; // can be unsigned long in 64 bit
} my_struct;
struct my_struct val;

func(&val.val1);

void func(unsigned int *)
{
// val1 can be deferenced
}

Is there workaround in case of 64bit?
 
I

Ian Collins

It's like..
What's like? Please quote what you are replying to, see
struct {
size_t val1; // can be unsigned long in 64 bit
} my_struct;
struct my_struct val;

func(&val.val1);

void func(unsigned int *)
{
// val1 can be deferenced
}

Is there workaround in case of 64bit?
You should get a diagnostic as you are passing a pointer to an
incompatible type.
 
S

sureshjayaram

Iam getting warning message only in 64bit m/c warning: passing argument
... from incompatible pointer type
How to solve this?
 
I

Ian Collins

Iam getting warning message only in 64bit m/c warning: passing argument
... from incompatible pointer type
How to solve this?
Solve what? I asked you politely to quote context. If you don't want
to help me, I won't help you.
 
S

sureshjayaram

Sorry I did't notice the first part of the previous message. I should
have provided the context in the first place.

I have problem with the code only with 64 bit big endian machine.
i have a member size_t val1 in my structure. The size of size_t is
32(unsigned int) in 32 bit machines and 64(unsigned long) in 64 bit
machines.

I am passing address of this variable to a different function (where it

accepts only pointer to unsigned int) unsigned int *. Basically passing

a unsigned long pointer instead of unsigned int pointer. I think the
value is getting truncated while dereferencing int *. In this case how
do I make my code portable? Can functions like htonl/ntohl will help?
or casting could be of any help?

struct {
size_t val1; // can be unsigned long in 64 bit
} my_struct;
struct my_struct val;

func(&val.val1);

void func(unsigned int *val1)
{
// val1 can be deferenced here
}

When I dereference I will be getting only the truncated 32 bits which
is giving wrong value.

The below example when run on 3 different arch (i386, ia64 & s390x)
provided different output which confirms the same

#include <stdio.h>

int main()
{
size_t i = 1524;
unsigned int *k = &i;

printf("i is %d\n*k is %d\n", i, *k);
}

On i386
1524
1524

on ia64
1524
1524

on s390x (big endian)
1524
0
 
G

Gordon Burditt

I have problem with the code only with 64 bit big endian machine.
i have a member size_t val1 in my structure.
The size of size_t is
32(unsigned int) in 32 bit machines and 64(unsigned long) in 64 bit
machines.

I'm not convinced this generalization is valid for all 32-bit or
64-bit machines.
I am passing address of this variable to a different function (where it

accepts only pointer to unsigned int) unsigned int *.

This is your problem. Fix it. There are several approaches:

(1) Fix the function to accept a pointer to size_t.
(2) Copy the size_t into an unsigned int (by assignment), and pass a
pointer to *THAT*. If the function might change the value pointed
at, copy it back afterwards. However, you're going to have trouble
if the value won't FIT in an unsigned int, which itself presents problems.
(3) Change the type of the member to unsigned int.
Basically passing
a unsigned long pointer instead of unsigned int pointer. I think the
value is getting truncated while dereferencing int *. In this case how
do I make my code portable?

Fix the type mismatch so the types no longer mismatch.
Can functions like htonl/ntohl will help? No.

or casting could be of any help?

Casting of *pointers* won't help here. Casting of values
might, but that's not what you are passing.

Gordon L. Burditt
 
I

Ian Collins

Gordon said:
I'm not convinced this generalization is valid for all 32-bit or
64-bit machines.
size_t has to be able to hold the largest size value, so it has to be 64
bit on a 64 bit system.
This is your problem. Fix it. There are several approaches:

(1) Fix the function to accept a pointer to size_t.
(2) Copy the size_t into an unsigned int (by assignment), and pass a
pointer to *THAT*. If the function might change the value pointed
at, copy it back afterwards. However, you're going to have trouble
if the value won't FIT in an unsigned int, which itself presents problems.
(3) Change the type of the member to unsigned int.
Agreed, 1 is the preferred solution.
 
S

sureshjayaram

This is your problem. Fix it. There are several approaches:
(1) Fix the function to accept a pointer to size_t.

I may not be able to do because the function is supplied by a
library.
(2) Copy the size_t into an unsigned int (by assignment), and pass a
> pointer to *THAT*. If the function might change the value pointed
> at, copy it back afterwards. However, you're going to have trouble
> if the value won't FIT in an unsigned int, which itself presents
problems.

This is possible. The value will always fit in unsigned int.
(3) Change the type of the member to unsigned int.

This is also not possible as the data type definition is provided by
some other library.
 
F

Flash Gordon

Ian said:
size_t has to be able to hold the largest size value, so it has to be 64
bit on a 64 bit system.

Just because the system is 64 bit does not mean the compiler has to
allow you to create a single object with a size that won't fit in a 32
bit size_t. If it doesn't allow you to create such a large object, why
make size_t 64 bits?
Agreed, 1 is the preferred solution.

Agreed.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc

Inviato da X-Privat.Org - Registrazione gratuita http://www.x-privat.org/join.php
 
C

CBFalconer

Sorry I did't notice the first part of the previous message. I
should have provided the context in the first place.

You are obviously unaware of the problems with the foul google
interface to usenet. Read the following sig, and the URLs
referenced in it. Do so before posting again.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
G

Gordon Burditt

I have problem with the code only with 64 bit big endian machine.
size_t has to be able to hold the largest size value, so it has to be 64
bit on a 64 bit system.

No, it doesn't. It could be 10240 bits, or a whole bunch of values
all >= 64 bits.

There is also the possibility that this is a smegmented architecture,
with the maximum size of a smegment (and therefore an object) being
2**32. This is the case for the Intel x86 large-code (32 bits),
small-data (16 bits) model where size_t is 16 bits.


How is a N-bit system defined again? I thought a system was N-bit
if an int had N bits. In that case, this 64-bit machine with a
64-bit unsigned long and a 32-bit unsigned int ISN'T a 64-bit machine.

Other possible definitions include:
- The width of a code pointer.
- The width of a data pointer.
(Note: the above two can be different. See "medium" and "compact" models
on an Intel [2345]86. Note that a Pentium can be considered a 48-bit
machine by this definition.)
- The value given in marketing literature (in which case it's
meaningless).
- The width of the memory data bus (in which case machines like the
8088 and 8086 have different bittedness but virtually identical
software architecture.)

Gordon L. Burditt
 
I

Ian Collins

Flash said:
Just because the system is 64 bit does not mean the compiler has to
allow you to create a single object with a size that won't fit in a 32
bit size_t. If it doesn't allow you to create such a large object, why
make size_t 64 bits?
Are you aware of such a system?
 
F

Flash Gordon

Gordon Burditt wrote:

(Note: the above two can be different. See "medium" and "compact" models
on an Intel [2345]86. Note that a Pentium can be considered a 48-bit
machine by this definition.)
- The value given in marketing literature (in which case it's
meaningless).
- The width of the memory data bus (in which case machines like the
8088 and 8086 have different bittedness but virtually identical
software architecture.)

You should have picked the 80386SX and 30386DX (IIRC) where the SX had a
16 bit data bus (so it could more easily be used in circuits designed
for a 286) and the DX had a 32 bit data bus but they had *identical*
instruction sets. :)
 
G

Gordon Burditt

Just because the system is 64 bit does not mean the compiler has to
Are you aware of such a system?

Well, there's one that's close: Intel Pentium in 32-bit mode.
(People seem to mean that an N-bit system has N *address* bits. In
the original posting, if bittedness is determined by the size of
int, a 64-bit system with a 32-bit unsigned int *ISN'T* 64 bits).
The pointers are 48 bits, but they are segmented, and the largest
segment is 4G.

Going down in size a bit, consider Intel Pentium in 16-bit mode
large model. The largest object is 64k, although pointers are
32-bits. size_t is 16 bits. You *can* do funky things with pointer
arithmetic to carry into the segment, but that's called "huge model".

Gordon L. Burditt
 
I

Ian Collins

Gordon said:
Well, there's one that's close: Intel Pentium in 32-bit mode.
(People seem to mean that an N-bit system has N *address* bits. In
the original posting, if bittedness is determined by the size of
int, a 64-bit system with a 32-bit unsigned int *ISN'T* 64 bits).
The pointers are 48 bits, but they are segmented, and the largest
segment is 4G.

Going down in size a bit, consider Intel Pentium in 16-bit mode
large model. The largest object is 64k, although pointers are
32-bits. size_t is 16 bits. You *can* do funky things with pointer
arithmetic to carry into the segment, but that's called "huge model".
I've spent many a happy hour tinkering with Intel's segmented
architecture, but I'm not aware of any current 64 bit system that would
use a 32 bit size_t.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top