Typecasting pointers

B

Bernhard Holzmayer

Nishu said:
Hi All,

Is it valid in C to typecast a pointer?

eg. code snippet... considering int as 16 bit and long as 32 bit.

int *variable, value;

*((long*)variable)++ = value;
*((long*)variable)++ = value;
*((long*)variable)++ = value;
*((long*)variable)++ = value;

Thanks,
Nishu


Minimalistic answer:
int *variable, value;

*( (int *)( ((long*)variable)++ )) = value;
*( (int *)( ((long*)variable)++ )) = value;
*( (int *)( ((long*)variable)++ )) = value;
*( (int *)( ((long*)variable)++ )) = value;

should work, provided that the address where variable points to,
has been initialized somewhere else.

Long answer:
Before assigning the value, the pointer should be cast back to the correct
type. (Implicit type propagation would do this for you, but that's not
desirable here.)

It will copy 'value' to four address locations with one int between,
which will not be updated. Only every 2nd address location will be written.
My guess: This is not what you want.

However, if you really intend this and would like to make this thing more
evident, you might want to use a structural method like this:

struct wr {
int a;
int b;
};
struct wr * variable; // again: memory must be defined somewhere!
int value;

now using
variable++>a = value;
variable++>a = value;
variable++>a = value;
variable++>a = value;

would result in the same effect, but is much more readable, avoids casts and
is much less error prone.

But keep in mind, that structures can contain additional management
components which aren't visible. So, the physical layout in memory might
differ or at least be machine dependent.

Bernhard
 
R

Richard Heathfield

Bernhard Holzmayer said:

Minimalistic answer:
int *variable, value;

*( (int *)( ((long*)variable)++ )) = value;
*( (int *)( ((long*)variable)++ )) = value;
*( (int *)( ((long*)variable)++ )) = value;
*( (int *)( ((long*)variable)++ )) = value;

should work, provided that the address where variable points to,
has been initialized somewhere else.

No, it shouldn't, partly because ((long*)variable)++ is incorrect. You can
only use ++ on objects, not values. Alignment problems remain, too. This is
the wrong solution all round.
 
B

Bernhard Holzmayer

Richard said:
No, it shouldn't, partly because ((long*)variable)++ is incorrect. You can
only use ++ on objects, not values. Alignment problems remain, too. This
is the wrong solution all round.

Sorry, please explain this. Here's my understanding:

int * variable;

tells us that variable is a pointer, correct? -- So

variable++;
((int *)variable)++;

are the same correct increment command, since the (useless) cast
doesn't change anything. If this results in a valid pointer,

*((int *)variable++)
*((long *)variable++)

should both mean valid lvalues, so that the assignment should work.
However, if size of pointers aren't equal, the second line makes no sense.

gcc -Wall eats the first without any comment,
in the second it warns (as you did!), that
"result of cast expressions shouldn't be used as lvalues".

I agree, that all this casting is ugly and not necessary at all,
if not a very strange compiler would take advantage of it.

From the standard's view, however, I don't understand where it breaks any
rule:
cast result of a pointer should result in a pointer again.
And increment operation is permitted on pointers.
The result of the pointer incrementation is a pointer again.
So it can be dereferenced and the assignment should hold, too.

Where am I wrong?

Bernhard
 
G

Guest

Bernhard said:
Sorry, please explain this. Here's my understanding:

int * variable;

tells us that variable is a pointer, correct? -- So

variable++;
((int *)variable)++;

are the same correct increment command, since the (useless) cast
doesn't change anything.

No. The cast does change something: it stops the expression from being
an lvalue. You can compare it to (variable + 0)++ or to (&*variable)+
+. Neither of those will work.
 
R

Richard Tobin

Bernhard Holzmayer said:
variable++;
((int *)variable)++;

are the same correct increment command, since the (useless) cast
doesn't change anything.

No, the second is not legal. A cast expression is not an lvalue.
From the standard's view, however, I don't understand where it breaks any
rule:
cast result of a pointer should result in a pointer again.

Yes, it results in a pointer, but not an lvalue.
And increment operation is permitted on pointers.

Only on pointers that are lvalues.

You can imagine what these expressions would mean if they were legal.
In fact at one point in the drafting of the original ANSI standard
they *were* legal, but this was changed.

-- Richard
 
C

Chris Dollin

Bernhard said:
Sorry, please explain this. Here's my understanding:

int * variable;

tells us that variable is a pointer, correct? -- So

variable++;
((int *)variable)++;

are the same correct increment command, since the (useless) cast
doesn't change anything.

Contrarywise: it changes a /variable/ into a /value/. You might as
well say of

(variable + 0)++;

that it was a correct increment command, since the (useless) addition
of 0 doesn't change anything.

You can argue (but not here, please) that the case /ought not/ to
have this effect, but in Standard C, it does.
 
B

Bernhard Holzmayer

Bernhard said:
Sorry, please explain this.

Thanks for clarification.

Especially to Richard for pointing out that such things were legal at times
when I started to use C ... (> 15 years ago).

Bernhard
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top