473,495 Members | 1,967 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Differences between pointers

Hello,

Just a clarification of the specification about the C-Standard's
interpretation of pointers.

I know that 'char *' and 'void *' are equivalent and that 'int *' may be
different in representation to 'char *' (but most often there is no
difference on modern compilers/machines).

So if I define a function such as (e.g. often for callbacks)

void foo(void *data);

Then if I pass something that is a structure

struct testing {
int a;
char b;
};

int main(void)
{
struct testing x;
x.a = 1;
x.b = 2;

foo((void *)&x);
return 0;
}

is this concept valid? If not, what would be a valid way to achieve
portable results?

Best Regards,
Jason.
Nov 14 '05 #1
12 1442
On Wed, 13 Apr 2005 06:11:02 +0200, Jason Curl
<j_********@motorola.com> wrote in comp.lang.c:
Hello,

Just a clarification of the specification about the C-Standard's
interpretation of pointers.

I know that 'char *' and 'void *' are equivalent and that 'int *' may be
different in representation to 'char *' (but most often there is no
difference on modern compilers/machines).

So if I define a function such as (e.g. often for callbacks)

void foo(void *data);

Then if I pass something that is a structure

struct testing {
int a;
char b;
};

int main(void)
{
struct testing x;
x.a = 1;
x.b = 2;

foo((void *)&x);
The cast is unnecessary. The & operator takes the address of its
operand yielding a value of pointer to type, in this case pointer to
struct testing. In C, no cast is required to convert between pointer
to void and pointer to any other object type, not in either direction.

So rewrite this as:

foo(&x);
return 0;
}

is this concept valid? If not, what would be a valid way to achieve
portable results?

Best Regards,
Jason.


The concept is perfectly valid and portable as far as the code you
wrote. Actually using the pointer is another matter. It must be
converted to a pointer to object type before it can be used to
actually read or write values.

The only portable types it may be converted to are pointer to struct
testing, or pointer to int, in which case it will point to the 'a'
member of the testing structure.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #2
Jason Curl wrote:
Hello,

Just a clarification of the specification about the C-Standard's
interpretation of pointers.

I know that 'char *' and 'void *' are equivalent and that 'int *' may be
different in representation to 'char *' (but most often there is no
difference on modern compilers/machines).

So if I define a function such as (e.g. often for callbacks)

void foo(void *data);

Then if I pass something that is a structure

struct testing {
int a;
char b;
};

int main(void)
{
struct testing x;
x.a = 1;
x.b = 2;

foo((void *)&x);
return 0;
}

is this concept valid? If not, what would be a valid way to achieve
portable results?

Best Regards,
Jason.

Why don't you write your code like this ?
void foo(struct testing *data)????

--
Just when you felt lonely, you began to miss me.
When I was missing you, I falled into lonely.
Nov 14 '05 #3
Jack Klein <ja*******@spamcop.net> wrote:
On Wed, 13 Apr 2005 06:11:02 +0200, Jason Curl
<j_********@motorola.com> wrote in comp.lang.c:
I know that 'char *' and 'void *' are equivalent
Well... almost. They're required to have identical representation and
alignment, but only void * can be assigned to and from other object
pointers without casting.
So if I define a function such as (e.g. often for callbacks)

void foo(void *data);

Then if I pass something that is a structure

struct testing {
int a;
char b;
};

int main(void)
{
struct testing x;
x.a = 1;
x.b = 2;

foo((void *)&x);
The cast is unnecessary.

The concept is perfectly valid and portable as far as the code you
wrote. Actually using the pointer is another matter. It must be
converted to a pointer to object type before it can be used to
actually read or write values.

The only portable types it may be converted to are pointer to struct
testing, or pointer to int, in which case it will point to the 'a'
member of the testing structure.


And a pointer to unsigned char, in which case it may be used to inspect
the memory representation of the struct (which is implementation-
specific, and may (probably will) include padding bytes).

Richard
Nov 14 '05 #4
Jack Klein wrote:
On Wed, 13 Apr 2005 06:11:02 +0200, Jason Curl
<j_********@motorola.com> wrote in comp.lang.c:

Hello,

Just a clarification of the specification about the C-Standard's
interpretation of pointers.

I know that 'char *' and 'void *' are equivalent and that 'int *' may be
different in representation to 'char *' (but most often there is no
difference on modern compilers/machines).

So if I define a function such as (e.g. often for callbacks)

void foo(void *data);

Then if I pass something that is a structure

struct testing {
int a;
char b;
};

int main(void)
{
struct testing x;
x.a = 1;
x.b = 2;

foo((void *)&x);

The cast is unnecessary. The & operator takes the address of its
operand yielding a value of pointer to type, in this case pointer to
struct testing. In C, no cast is required to convert between pointer
to void and pointer to any other object type, not in either direction.

So rewrite this as:

foo(&x);

return 0;
}

is this concept valid? If not, what would be a valid way to achieve
portable results?

Best Regards,
Jason.

The concept is perfectly valid and portable as far as the code you
wrote. Actually using the pointer is another matter. It must be
converted to a pointer to object type before it can be used to
actually read or write values.

The only portable types it may be converted to are pointer to struct
testing, or pointer to int, in which case it will point to the 'a'
member of the testing structure.

Jack - because void* and int* can have a different internal
representation, can the size of the pointers change also? Or does the
C-spec state the size of the ptrs are the same?

Can there be an esoteric machine (or even just a compiler) built that
sizeof(void*)==4 and sizeof(int*)==6, so when the type cast is done,
data is lost on the function call resulting in an invalid pointer when
it's typecasted back from void* to int*?

If this is really the case, would the solution that I use the signature:

void foo(int*);

and then I can have

struct testing1 {
int a;
char b;
};

struct testing2 {
int a;
char *str;
}

and pass pointers to the structures typecasted to (int*)?

I find this question important for implementing, say, generic message
queues on embedded systems (where it's easy to have the first member of
the struct an int, that defines the message, and the remaining data in
the struct being the message).

Thanks again.
Jason.

Nov 14 '05 #5
Phenix Zhang wrote:

Jason Curl wrote:
Hello,

Just a clarification of the specification about the C-Standard's
interpretation of pointers.

I know that 'char *' and 'void *'
are equivalent and that 'int *' may be
different in representation to 'char *' (but most often there is no
difference on modern compilers/machines).

So if I define a function such as (e.g. often for callbacks)

void foo(void *data);

Then if I pass something that is a structure

struct testing {
int a;
char b;
};

int main(void)
{
struct testing x;
x.a = 1;
x.b = 2;

foo((void *)&x);
return 0;
}

is this concept valid? If not, what would be a valid way to achieve
portable results?

Best Regards,
Jason.

Why don't you write your code like this ?
void foo(struct testing *data)????


That's what I think. It's not a generic function,
meant to work with pointers to various different types of data.

--
pete
Nov 14 '05 #6
Jason Curl <j_********@motorola.com> writes:
[...]
Jack - because void* and int* can have a different internal
representation, can the size of the pointers change also? Or does the
C-spec state the size of the ptrs are the same?
I'm not Jack, but ...

There's no requirement that void* and int* have to be the same type.
Can there be an esoteric machine (or even just a compiler) built that
sizeof(void*)==4 and sizeof(int*)==6, so when the type cast is done,
data is lost on the function call resulting in an invalid pointer when
it's typecasted back from void* to int*?


I believe that conversion from int* to void* and back to int* is
guaranteed to yield a value equal to the original value. (If that
weren't the case, void* wouldn't be usable as a generic pointer type.)

If int* and void* are of different sizes, it's more likely that void*
is bigger. More information may be needed to point to any arbitrary
byte than to point to an integer. For example, a raw machine address
might point to a word, with a void* or char* consisting of a word
pointer plus an offset.

(I've never seen an implementation where int* and void* are of
different sizes; I've used systems with native word poitenrs, but the
offset for a void* or char* was stored in the unused high-order bits.)

--
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.
Nov 14 '05 #7
Jason Curl wrote:

<snip>
Jack - because void* and int* can have a different internal
representation, can the size of the pointers change also? Or does the
C-spec state the size of the ptrs are the same?
I'm not aware of anything that says the pointer sizes have to be the
same, but there are other guarantees that help you here...
Can there be an esoteric machine (or even just a compiler) built that
sizeof(void*)==4 and sizeof(int*)==6, so when the type cast is done,
data is lost on the function call resulting in an invalid pointer when
it's typecasted back from void* to int*?
The standard guarantees that you can assign any pointer to an object to
a pointer to void and then back and end up with a pointer to the
original type. I.e this will always work:

T foo;
T *fooptr = &foo;
void *vptr = fooptr;
T *foo2ptr = vptr;
if (fooptr == foo2ptr)
puts("Executed on all conforming implementations");

Note that the above is not guaranteed for function pointers.
If this is really the case, would the solution that I use the signature:

void foo(int*);

and then I can have

struct testing1 {
int a;
char b;
};

struct testing2 {
int a;
char *str;
}

and pass pointers to the structures typecasted to (int*)?

I find this question important for implementing, say, generic message
queues on embedded systems (where it's easy to have the first member of
the struct an int, that defines the message, and the remaining data in
the struct being the message).


Fortunately for you, there is another guarantee that further helps you
here. With two struct definitions that share a common initial set of
fields, i.e. the "int a" in your example above, those initial fields are
guaranteed to have the same layout. I believe you are also guaranteed to
have no padding before the *first* field.

I may not be Jack, but I'm sure someone will correct me if I've made a
mistake.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #8
Jason Curl wrote:

Just a clarification of the specification about the C-Standard's
interpretation of pointers.

I know that 'char *' and 'void *' are equivalent and that 'int *'
may be different in representation to 'char *' (but most often
there is no difference on modern compilers/machines).

So if I define a function such as (e.g. often for callbacks)

void foo(void *data);

Then if I pass something that is a structure

struct testing {
int a;
char b;
};

int main(void)
{
struct testing x;
x.a = 1;
x.b = 2;

foo((void *)&x);
return 0;
}

is this concept valid? If not, what would be a valid way to achieve
portable results?


It's fine. However the cast is unnecessary and can prevent the
compiler from flagging errors, so remove it. Then the foo
implementation should include:

void foo(void *data)
{
struct testing *dp = data;

/* code using dp, and not data */
}

and you will note there is no sign of a cast anywhere. All this
allows that void* pointer to pass through various levels of
software that don't care exactly what it points to, with only the
originator and destination actually caring (or knowing).

Removing the cast from the caller means that if you ever alter foo
to specify the parameter type more closely (i.e. as a non-void*)
you will get a compiler error. With the caller cast the error will
be ignored.

--
"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
Nov 14 '05 #9
Keith Thompson <ks***@mib.org> wrote:
Jason Curl <j_********@motorola.com> writes:
[...]
Jack - because void* and int* can have a different internal
representation, can the size of the pointers change also? Or does the
C-spec state the size of the ptrs are the same?
I'm not Jack, but ...

There's no requirement that void* and int* have to be the same type.


Erm.

void * and int * _are_ not the same type. One is a pointer to void, the
other a pointer to int.

YM "the same size", I presume.
Can there be an esoteric machine (or even just a compiler) built that
sizeof(void*)==4 and sizeof(int*)==6, so when the type cast is done,
data is lost on the function call resulting in an invalid pointer when
it's typecasted back from void* to int*?


I believe that conversion from int* to void* and back to int* is
guaranteed to yield a value equal to the original value.


'tis. Ditto for any other object pointer type: to void *, and back to
the _original_ type, must always work correctly. To void *, and "back"
to another type, need not work at all.
If int* and void* are of different sizes, it's more likely that void*
is bigger.


More likely, but not guaranteed; but even when int * is larger, the
transfer through void * must still work. This means that a larger int *
must contain padding bits, but that's allowed.

Richard
Nov 14 '05 #10
rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
Keith Thompson <ks***@mib.org> wrote:
Jason Curl <j_********@motorola.com> writes:
[...]
> Jack - because void* and int* can have a different internal
> representation, can the size of the pointers change also? Or does the
> C-spec state the size of the ptrs are the same?


I'm not Jack, but ...

There's no requirement that void* and int* have to be the same type.


Erm.

void * and int * _are_ not the same type. One is a pointer to void, the
other a pointer to int.

YM "the same size", I presume.


D'oh! Yes, I meant the same size.

[...]
If int* and void* are of different sizes, it's more likely that void*
is bigger.


More likely, but not guaranteed; but even when int * is larger, the
transfer through void * must still work. This means that a larger int *
must contain padding bits, but that's allowed.


[Low-level nitpicking follows. Stop reading now if you value your
sanity.]

Basically correct, but strictly speaking the term "padding bits"
applies only to integer types. Also, it refers to a disinct subset of
the bits of a type representation, bits that don't contribute to the
value, but that doesn't necessarily apply in this case.

One off-the-wall example is that void* might be represented as a pure
binary machine address, and int* might be represented in biquinary
(7 bits per decimal digit). All the bits contribute to the value, so
there are no padding bits; it's just an inefficient representation.

Or if you prefer a more binary representation, you can double the size
with a mapping like:

00 --> 0001
01 --> 0010
10 --> 0100
11 --> 1000

This is, of course, totally unrealistic, though I suspect some
versions of the mythical DS9K use this representation (or something
even worse).

The standard talks about padding bits for integer types because it
places strong constraints on how integers are represented. There are
virtually no constraints on pointer representations (other than that
they're made of bits and bytes and can, like any type, be viewed as
arrays of unsigned char).

--
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.
Nov 14 '05 #11
Keith Thompson wrote:
rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
Keith Thompson <ks***@mib.org> wrote:
If int* and void* are of different sizes, it's more likely that void* is bigger.


More likely, but not guaranteed; but even when int * is larger, the
transfer through void * must still work. This means that a larger int * must contain padding bits, but that's allowed.


[Low-level nitpicking follows. Stop reading now if you value your
sanity.]

Basically correct, but strictly speaking the term "padding bits"
applies only to integer types.


Since we're nitpicking ;), it's not as if the committee _invented_ the
term 'padding bits'. The term is not in italics within C99. Indeed, the
term 'padding' is used exclusively as a qualification without explicit
definition.

--
Peter

Nov 14 '05 #12
Peter Nilsson wrote:

Keith Thompson wrote:
rl*@hoekstra-uitgeverij.nl (Richard Bos) writes:
Keith Thompson <ks***@mib.org> wrote:
> If int* and void* are of different sizes,
> it's more likely that void*
> is bigger.

More likely, but not guaranteed;
but even when int * is larger, the
transfer through void * must still work.
This means that a larger int *
must contain padding bits, but that's allowed.


[Low-level nitpicking follows. Stop reading now if you value your
sanity.]

Basically correct, but strictly speaking the term "padding bits"
applies only to integer types.


Since we're nitpicking ;), it's not as if the committee _invented_ the
term 'padding bits'.
The term is not in italics within C99. Indeed, the
term 'padding' is used exclusively as a qualification without explicit
definition.


C does not allow bitwise operations
on any other types besides integer types.
No other types besides integer types, are described in
the standard as being decomposable into various kinds of bits.
Whether or not your pointer has a sign bit, is off topic
with regard to portable C programming.

--
pete
Nov 14 '05 #13

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

Similar topics

1
5835
by: Chris Grimble | last post by:
I have a very simple applet that I am trying to make compatible with both Microsoft's JVM and Suns JVM in Internet Explorer. However, when I turn on the Sun JVM it works occasionally, but...
0
1890
by: Dan Gass | last post by:
The difflib.py module and the diff.py tools script in Python 2.4 alpha 3 now support generating side by side (with intra line differences) in HTML format. I have found this useful for performing...
5
15918
by: Rasti | last post by:
Hello, I am trying to translate a C++ script to Java. Are there any differences between the C++ this-pointer and the Java this-pointer? Thank you
14
2043
by: Bern | last post by:
what are all the diferences between the two?
6
2523
by: gustav04 | last post by:
hi all i have a question: what is the difference between a c-function and an c++ class method (both do exactly the same thing). lets say, i have a function called print2std() and a class...
13
9604
by: Kieran | last post by:
I am designing a content management system and I want to make sure all pages entered into it's database by users are using valid HTML. I have designed the system to use HTML 4.01 Transitional...
15
6944
by: Paul Morrison | last post by:
Hi all, I need to come up with some differences between arrays in Java and C, I have searched Google and so far all I have found is the following: Arrays in Java are reference types with...
4
4141
by: | last post by:
Hi, does anyone know what would be the (most common) reasons to get difference answers in VC++.net between running in release and debug ? Thanks, JC
3
1151
by: Rich | last post by:
Hello, I recently started using delegates in my VB apps to handle asynchronous operations. Based on the examples that I followed, delegates appear to work in a similar way as Interfaces. ...
0
7120
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
6991
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7196
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
6878
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
7373
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...
1
4897
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3078
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1405
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
649
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.