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. 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
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.
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
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.
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
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.
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.
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
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 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.
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
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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...
|
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...
|
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
|
by: Bern |
last post by:
what are all the diferences between the two?
|
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...
| |
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...
|
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...
|
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
|
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. ...
|
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,...
|
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...
| |
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...
|
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...
|
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...
|
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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 ...
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |