Searching \ for '[OT:] Basic C pointer problem' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/language/index.htm?key=basic
Search entire site for: 'Basic C pointer problem'.

Exact match. Not showing close matches.
PICList Thread
'[OT:] Basic C pointer problem'
2004\07\22@001653 by Thomas

picon face
Hi,

I am having some trouble with this code:
void main(void)
{
   struct {
       char t1;
       int t2;
   } Test[2];

   int *var;
   var = &Test;
}
I am using MCC18 compiler.  What I want to do is to
get the starting address of the structure named
"Test".  The compiler message is: "type mismatch in
assignment".  Anyone know what my problem is?  Thank
you in advance!
Regards,
Thomas




__________________________________
Do you Yahoo!?
Yahoo! Mail - 50x more storage than other providers!
http://promotions.yahoo.com/new_mail

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\07\22@002505 by Thomas

picon face
Never mind!  I solved it:
void main(void)
{
       struct x{
               char t1;
               int t2;
       };

       struct x Test[2], *var;
       var = Test;
}

--- Thomas <spam_OUTmcu_stuffTakeThisOuTspamYAHOO.COM> wrote:
{Quote hidden}

__________________________________
Do you Yahoo!?
Vote for the stars of Yahoo!'s next ad campaign!
http://advision.webevents.yahoo.com/yahoo/votelifeengine/

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\07\22@004948 by john chung

flavicon
face
Thomas wrote:

{Quote hidden}

   you would have to write the following

  struct {
       char t1;
       int t2;
   } Test[2];

   int *var;
   var = (int*)&Test;



{Quote hidden}

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\07\22@010003 by Robert B.

flavicon
face
Couldn't you just use a void * declaration and avoid the type-cast?  Pointer
arithmetic won't work with that struct as an int* or char* so there's really
no point in declaring it that way.  I'll be the first to admit my C's a bit
rusty though...

>     you would have to write the following
>
>    struct {
>         char t1;
>         int t2;
>     } Test[2];
>
>     int *var;
>     var = (int*)&Test;

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\07\22@012408 by Thomas

picon face
Never mind!  I solved it:
void main(void)
{
       struct x{
               char t1;
               int t2;
       };

       struct x Test[2], *var;
       var = Test;
}

--- Thomas <.....mcu_stuffKILLspamspam@spam@YAHOO.COM> wrote:
{Quote hidden}

__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - Send 10MB messages!
http://promotions.yahoo.com/new_mail

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\07\22@012824 by john chung

flavicon
face
Robert B. wrote:

>Couldn't you just use a void * declaration and avoid the type-cast?  Pointer
>arithmetic won't work with that struct as an int* or char* so there's really
>no point in declaring it that way.  I'll be the first to admit my C's a bit
>rusty though...
>
>
>

   Actually the solution I gave can work but it is NOT recommended,
since the var pointer
treats the object as int. I could use void * var but I can't dereference
the object using the
var pointer. In short don't change the type for structs and unions.

John

{Quote hidden}

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\07\22@021051 by Thomas

picon face
Hi,

Thank you for your reply. I tried your method and it
seems to work.  I still have one question, though.  If
you look at the last two lines of code, I write 0 to
"var", then increment it.  For some reason, the value
of "var" is incremented by 2 bytes.  Is this normal?
How do I increment it by only 1 byte?

Someone mentioned about a void * and void casting...
what are they?!  How do they look like?

void main (void)
{
  struct {
       char t1;
       int t2;
   } Test[2];

   int *var;
   var = (int*)&Test;

   var = 0;    // write zero to var
   var++;      // var = 2, should it be equal 1 ?????
}

Thomas
--- john chung <johncspamKILLspamXYBASE.COM> wrote:
{Quote hidden}

__________________________________
Do you Yahoo!?
Vote for the stars of Yahoo!'s next ad campaign!
http://advision.webevents.yahoo.com/yahoo/votelifeengine/

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\07\22@023959 by john chung

flavicon
face
Hi,

   Pointer arithmetic can be a real mystery at times but
becomes easy with the right explaination.
When you increment a pointer , it actually increments by the size of
one element that is pointing too. That means if type int takes up
2 bytes then the pointer actually increments by 2 bytes.*based on the
last 2 lines that you added*

another example is:

struct mystruct{
       char t1;
       int t2;
   } Test[2];

struct mystruct *pstruct = 0;
pstruct++; // pstruct = pstruct + sizeof(*pstruct);

the pointer should point 3 bytes away since char takes
up one byte and int takes up 2 bytes. *Please* note
that the size of the types is implementation defined.

John




Thomas wrote:

{Quote hidden}

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\07\22@213318 by Ryan Underwood

flavicon
face
On Thu, Jul 22, 2004 at 02:42:21PM +0800, john chung wrote:
> Hi,
>
>    Pointer arithmetic can be a real mystery at times but
> becomes easy with the right explaination.
> When you increment a pointer , it actually increments by the size of
> one element that is pointing too.

Right; this is the same behavior that makes:
int x[5];
char y;
...
assert(x[y] == y[x]);

behave correctly.  (Indexing into an array is exactly equivalent to
pointer arithmetic semantics.)

{Quote hidden}

It is also implementation defined whether the struct is packed or not.
In a lot of implementations, there are memory alignment requirements on
the target which require members to reside on e.g. 32-bit boundaries for
decent performance or to work at all.  In these cases, sizeof(the
struct) will actually come out to be bigger than the total storage size
of the struct members, due to the padding.  Your example still works,
but e.g. trying to do *((int*)(mystruct + sizeof(char))) would not
necessarily give you the expected results (...although this is a rather
stupid way to get the value of a struct member...)

This struct packing is one reason why it is not portable to simply
memcpy/fwrite a struct into a file and then memcpy/fread to get it back
out.  You must either make sure that both ends are using the same
packing pragma, or write/read the member variables one at a time.  Since
it is virtually impossible to ensure that two different compilers are
using the same packing pragma, the safest bet is the latter.

--
Ryan Underwood, <EraseMEnemesisspam_OUTspamTakeThisOuTicequake.net>

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\07\22@214356 by Ryan Underwood

flavicon
face
On Wed, Jul 21, 2004 at 11:11:52PM -0700, Thomas wrote:
> Thank you for your reply. I tried your method and it
> seems to work.  I still have one question, though.  If
> you look at the last two lines of code, I write 0 to
> "var", then increment it.  For some reason, the value
> of "var" is incremented by 2 bytes.  Is this normal?
> How do I increment it by only 1 byte?

Try something like ((uint8_t*)var)++;

> Someone mentioned about a void * and void casting...
> what are they?!  How do they look like?

A void * is just a pointer whose type (void) has no storage
size.  It is illegal to index into a void pointer, but you can
do arithmetic on it.  Adding 1 to a void pointer simply increases
the address by one.

Usually one would cast a pointer into a void * when the intent is to
play with the address directly without letting pointer arithmetic
semantics get in the way.  The void * can also be used for very
primitive polymorphism.  (Have your function take a void *, and then
cast it to the appropriate type based on the other parameters or state
of the program.  Or use it to get around type checking when you know
exactly what you're doing.):

MyVar foo;
void *bar = &foo;
int *baz = bar;

Now you have a int* pointing to a MyVar object.  Useful?  Rarely.
Without the void * in between, you'd have to do an explicit typecast to
avoid annoying the compiler:

MyVar foo;
int *baz = (int*)&MyVar;

Different techniques are useful in different situations.  It is rarely
a good idea to mix void*, typecasts, and pointer arithmetic unless you
have compiler warnings cranked to the max and know exactly what you are
doing.

--
Ryan Underwood, <nemesisspamspam_OUTicequake.net>

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\07\23@093429 by Bob Ammerman

picon face
>
> A void * is just a pointer whose type (void) has no storage
> size.  It is illegal to index into a void pointer, but you can
> do arithmetic on it.  Adding 1 to a void pointer simply increases
> the address by one.

This is incorrect. You _cannot_ perform arithmetic on a void *. About the
only things you can do with a void *  are assign other pointers to them,
assign them to one another, pass them as arguments, and convert them to a
pointer to another type.

Bob Ammerman
RAm Systems

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email @spam@listservKILLspamspammitvma.mit.edu with SET PICList DIGEST in the body

2004\07\23@102306 by Sergio Masci

picon face
----- Original Message -----
From: Bob Ammerman <KILLspamrammermanKILLspamspamVERIZON.NET>
To: <RemoveMEPICLISTTakeThisOuTspamMITVMA.MIT.EDU>
Sent: Friday, July 23, 2004 2:33 PM
Subject: Re: [OT:] Basic C pointer problem


{Quote hidden}

You are both correct. Some compilers treat "void *" as "char *" in expressions
(i.e. sizeof(void *) == sizeof(char *)), other compilers trap the use of "void
*". The previous poster is probably basing his remarks on his experience with a
particular compiler. As a rule you should treat "void *" as a pointer to
something of unknown size.

Regards
Sergio Masci

http://www.xcprod.com/titan/XCSB - optimising PIC compiler

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email spamBeGonelistservspamBeGonespammitvma.mit.edu with SET PICList DIGEST in the body

2004\07\23@112642 by Bob Ammerman

picon face
The ANSI standard states that you *cannot* perform arithmetic on a void *.
Any compiler that permits such behavior is not enforcing ANSI.

sizeof(void *) is legal, it returns the number of storage units occupied by
a void * (the actual pointer).

void *myvoidptr;
sizeof(*myvoidptr) is illegal because the number of storage units used by
something a void * points to is undefined.

Bob Ammerman
RAm Systems

{Original Message removed}

2004\07\23@114751 by Sergio Masci

picon face
----- Original Message -----
From: Bob Ammerman <TakeThisOuTrammermanEraseMEspamspam_OUTVERIZON.NET>
To: <RemoveMEPICLISTspamTakeThisOuTMITVMA.MIT.EDU>
Sent: Friday, July 23, 2004 4:26 PM
Subject: Re: [OT:] Basic C pointer problem


> The ANSI standard states that you *cannot* perform arithmetic on a void *.
> Any compiler that permits such behavior is not enforcing ANSI.

Yes I know. However I was trying to point out that sometimes people base their
understanding of the language on their use of a particular compiler. I myself
have used compilers which claim to be ANSI complient and yet allow ++ on a "void
*".

>
> sizeof(void *) is legal, it returns the number of storage units occupied by
> a void * (the actual pointer).
>
> void *myvoidptr;
> sizeof(*myvoidptr) is illegal because the number of storage units used by
> something a void * points to is undefined.

Right again (is there no stopping Bob today :-)

I actually meant "sizeof(*(void *)) == sizeof(*(char *))" I guess I should have
re-read my post 23 times instead of the useual 22 :-)

Regards
Sergio Masci

http://www.xcprod.com/titan/XCSB - optimising PIC compiler

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email listservEraseMEspam.....mitvma.mit.edu with SET PICList DIGEST in the body

2004\07\23@231945 by Jim Tellier

picon face
Bob Ammerman wrote:

> The ANSI standard states that you *cannot* perform arithmetic on a void *.
> Any compiler that permits such behavior is not enforcing ANSI.
Umm,, I think that depends upon which version of the ANSI standard you're
talking about.   If I recall correctly, that "restriction" only came about
with the introduction of the "const" concept.   Prior to that (and I
honestly
don't recall when that was, or (in the worst case) I'm confusing my C++ with
my "C" (! :^)... I think it was most often completely "legal" (by the
compiler
writer's rules) to do arithmetic on void *'s , even though it was (mostly)
frowned upon by the "purists" (in whose camp I generally pitch my tent).
I seem to recall lots of usage of void* explicitly for the purpose of doing
"address calculation", e.g. for register-address offsets, etc.
Eh?
Jim

> --
> http://www.piclist.com#nomail Going offline? Don't AutoReply us!
> email EraseMElistservspammitvma.mit.edu with SET PICList DIGEST in the body

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email RemoveMElistservEraseMEspamEraseMEmitvma.mit.edu with SET PICList DIGEST in the body

2004\07\23@235754 by Ryan Underwood

flavicon
face
On Fri, Jul 23, 2004 at 09:33:10AM -0400, Bob Ammerman wrote:
>
> This is incorrect. You _cannot_ perform arithmetic on a void *. About the
> only things you can do with a void *  are assign other pointers to them,
> assign them to one another, pass them as arguments, and convert them to a
> pointer to another type.

Bob, thanks for pointing that out.  I was generalizing based on gcc,
which only warns about void pointer arithmetic when -pedantic is
supplied (and still doesn't consider it an error even in ANSI mode).

--
Ryan Underwood, <RemoveMEnemesisspam_OUTspamKILLspamicequake.net>

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email RemoveMElistservTakeThisOuTspamspammitvma.mit.edu with SET PICList DIGEST in the body

2004\07\24@001453 by Ryan Underwood

flavicon
face
On Fri, Jul 23, 2004 at 09:33:10AM -0400, Bob Ammerman wrote:
> >
> > A void * is just a pointer whose type (void) has no storage
> > size.  It is illegal to index into a void pointer, but you can
> > do arithmetic on it.  Adding 1 to a void pointer simply increases
> > the address by one.
>
> This is incorrect. You _cannot_ perform arithmetic on a void *. About the
> only things you can do with a void *  are assign other pointers to them,
> assign them to one another, pass them as arguments, and convert them to a
> pointer to another type.

I just verified that g++ dies with a standards-compliance error:
/tmp/tmp.c:5: error: ISO C++ forbids incrementing a pointer of type `void*'

while gcc just complains (only with -pedantic):
/tmp/tmp.c:5: warning: wrong type argument to increment

So perhaps there is a discrepancy between the C and C++ standards, or
the GNU compiler is lax in enforcing them.

--
Ryan Underwood, <EraseMEnemesisspamspamspamBeGoneicequake.net>

--
http://www.piclist.com hint: To leave the PICList
RemoveMEpiclist-unsubscribe-requestKILLspamspammitvma.mit.edu

2004\07\24@110521 by Bob Ammerman

picon face
Nope!

Miscellaneous address calculations are (and were) generally done with char *
not void *.

IIRC the primary difference between ANSI C and C++ regarding void * is that
in C you can assign a void * to another pointer without a cast, but in C++
you need to do a cast.

Bob Ammerman
RAm Systems


{Original Message removed}

2004\07\24@112842 by John J. McDonough

flavicon
face
----- Original Message -----
From: "Bob Ammerman" <rammermanSTOPspamspamspam_OUTVERIZON.NET>
Subject: Re: [OT:] Basic C pointer problem


> IIRC the primary difference between ANSI C and C++ regarding void * is
that
> in C you can assign a void * to another pointer without a cast, but in C++
> you need to do a cast.

I think the difference is even smaller than that.  I believe in ANSI C it
generates a warning, in C++ an error (although in some compilers switches
can change that behavior).

--McD

--
http://www.piclist.com hint: To leave the PICList
spamBeGonepiclist-unsubscribe-requestSTOPspamspamEraseMEmitvma.mit.edu

2004\07\24@131537 by Ryan Underwood

flavicon
face
On Sat, Jul 24, 2004 at 11:03:57AM -0400, Bob Ammerman wrote:
> Nope!
>
> Miscellaneous address calculations are (and were) generally done with char *
> not void *.
>
> IIRC the primary difference between ANSI C and C++ regarding void * is that
> in C you can assign a void * to another pointer without a cast, but in C++
> you need to do a cast.

Yeah, from the C99 standard:

6.3.2.3 Pointers
1 A pointer to void may be converted to or from a pointer to any
incomplete or object type. A pointer to any incomplete or object type
may be converted to a pointer to void and back again; the result shall
compare equal to the original pointer.

Anyway, sizeof(void) == 1 on the GNU compiler, so that's why void
pointer arithmetic works. (It's semantically the same as arithmetic on a
byte pointer.)  I suspect it would also work in any other compiler where
sizeof(void) works and is nonzero.  According to the C99 standard,
sizeof() is not valid when applied to an incomplete type (such as void),
so even getting a value from this violates C99 semantics, if not
previous versions of the standard.

--
Ryan Underwood, <KILLspamnemesisspamBeGonespamicequake.net>

--
http://www.piclist.com hint: To leave the PICList
EraseMEpiclist-unsubscribe-requestspamEraseMEmitvma.mit.edu

More... (looser matching)
- Last day of these posts
- In 2004 , 2005 only
- Today
- New search...