C variable retyping

R

Rich Touper

C allows type casting in which a variable is converted from one type
to another.

Does C (whatever standard) allow the type of a variable to change,
within a statement, avoiding the conversion? And if so, provide an
example of how its done.

Example:
int a=23;
int b=34;
char c='a';
int * p_int=(int *) &c;

// type casting
// c is converted into type integer, then b is added.
(int) c + b;

//retypeing
(type int) c + b;
// similar action
*p_int + b

Ignoring alignment issues, storage size issues, etc., c is retyped to
an integer, no conversion is done, and c is used, within the
statement, as an integer, not a char.

Thanks
 
B

Ben Pfaff

Rich Touper said:
C allows type casting in which a variable is converted from one type
to another.

Does C (whatever standard) allow the type of a variable to change,
within a statement, avoiding the conversion? And if so, provide an
example of how its done.

No, C doesn't have that.
 
K

Keith Thompson

Shao Miller said:
Hmm... Not that I know of. As far as I know, there isn't any "type
casting" in C, but a value of some type can be converted to a value of
some other type.

"Type casting" is a common (but arguably incorrect) term for the cast
operator.

A conversion is an operation that takes a value of some type and
converts it to another type. A cast, written as a type name in
parentheses, is an operator that specifies such a conversion. There are
also implicit conversions.

"Type casting" is something that happens to TV and movie actors. :cool:}

Why would you want to do this? What are you trying to accomplish?

[...]
 
R

Rich Touper

As everyone pointed out, "converted" should be "promoted", and "during
evaluation" should have been tacked on the end. That would have helped
on the semantics of the question, but is still vague.
Hmm... Not that I know of. As far as I know, there isn't any "type
casting" in C, but a value of some type can be converted to a value of
some other type.

That seems to be the concensus of opinion. I certainly never heard of
it, but thought it may be an obscure, rarely used feature.
A few concerns with that last line including "alignment issues, storage
size issues, etc."

Wasn't attempting to start a huge thread on pointers, just using it to
illustrate a point.
I don't think so. The value of 'c' is converted to an 'int' value, that
is added to the value of 'b', then the result is unused. 'c' remains a
'char' throughout.

Exactly. The pomotion happens according to the standard, but only the
value of c is used, and because c is type char, 1 byte.
What is 'type'? It's not a C keyword. Is it some macro you haven't
shared?

I don't have a way to define it. But the point is IF c could be "retyped"
to an int, then sizeof(int) bytes would be used during evaluation. As
other posters pointed out, there would be alignment issues, unknown bytes
at &c+1 to &c+sizeof(int), etc...

I'll take this as a resounding NO. No such thing as "retyping".
Thanks
// similar action
*p_int + b
Assuming the original initialization of 'p_int' succeeded and still
points to the first byte of the object identified as 'c', the expression
'*p_int' attempts to re-interpret the bytes at the address of 'c' as an
object representation for an 'int' value.
Ignoring alignment issues, storage size issues, etc., c is retyped to
an integer, no conversion is done, and c is used, within the statement,
as an integer, not a char.

You can do similar things with unions for re-interpreting an object
representation of a value of one type as an object representation of a
value of a different type.

I don't understand why one would wish to ignore alignment issues,
storage size issues, etc.

To answer the only question in this post, you might be interested in C's
definition of "effective type." For example, in:

void * vp = malloc(sizeof (int[10]);

if 'malloc' succeeds, the object pointed to by 'vp' has no declared type
and no effective type. An effective type can later be established by
using an lvalue to read or modify the object.

int (* ten_ints)[10] = vp;

if (ten_ints) {
(*ten_ints)[0] = 1;
/* ... */
(*ten_ints)[9] = 10;
}

Now the effective type for the allocate storage has been established as
the type 'int[10]'.
 
S

Shao Miller

C allows type casting in which a variable is converted from one type
to another.

Hmm... Not that I know of. As far as I know, there isn't any "type
casting" in C, but a value of some type can be converted to a value of
some other type.
Does C (whatever standard) allow the type of a variable to change,
within a statement, avoiding the conversion? And if so, provide an
example of how its done.

Example:
int a=23;
int b=34;
char c='a';
int * p_int=(int *)&c;

A few concerns with that last line including "alignment issues, storage
size issues, etc."
// type casting
// c is converted into type integer, then b is added.
(int) c + b;

I don't think so. The value of 'c' is converted to an 'int' value, that
is added to the value of 'b', then the result is unused. 'c' remains a
'char' throughout.
//retypeing
(type int) c + b;

What is 'type'? It's not a C keyword. Is it some macro you haven't shared?
// similar action
*p_int + b

Assuming the original initialization of 'p_int' succeeded and still
points to the first byte of the object identified as 'c', the expression
'*p_int' attempts to re-interpret the bytes at the address of 'c' as an
object representation for an 'int' value.
Ignoring alignment issues, storage size issues, etc., c is retyped to
an integer, no conversion is done, and c is used, within the
statement, as an integer, not a char.

You can do similar things with unions for re-interpreting an object
representation of a value of one type as an object representation of a
value of a different type.

I don't understand why one would wish to ignore alignment issues,
storage size issues, etc.

To answer the only question in this post, you might be interested in C's
definition of "effective type." For example, in:

void * vp = malloc(sizeof (int[10]);

if 'malloc' succeeds, the object pointed to by 'vp' has no declared type
and no effective type. An effective type can later be established by
using an lvalue to read or modify the object.

int (* ten_ints)[10] = vp;

if (ten_ints) {
(*ten_ints)[0] = 1;
/* ... */
(*ten_ints)[9] = 10;
}

Now the effective type for the allocate storage has been established as
the type 'int[10]'.
 
S

Shao Miller

As everyone pointed out, "converted" should be "promoted", and "during
evaluation" should have been tacked on the end. That would have helped
on the semantics of the question, but is still vague.


That seems to be the concensus of opinion. I certainly never heard of
it, but thought it may be an obscure, rarely used feature.


Wasn't attempting to start a huge thread on pointers, just using it to
illustrate a point.


Exactly. The pomotion happens according to the standard, but only the
value of c is used, and because c is type char, 1 byte.

Promotion is due to rank. 'char' has a rank less than 'int' (and
'unsigned int' and 'signed int'). Rank is not the same as size.
I don't have a way to define it. But the point is IF c could be "retyped"
to an int, then sizeof(int) bytes would be used during evaluation. As
other posters pointed out, there would be alignment issues, unknown bytes
at&c+1 to&c+sizeof(int), etc...

I'll take this as a resounding NO. No such thing as "retyping".

Well for C99 and "simple types" (those that can be declared like "type
id")...

#define RETYPE(from_type, to_type, value) ( \
(union { from_type from; to_type to; }) \
{ .from = (value) } \
.to \
)

You can always 'typedef' "complicated types" to "simple types" and use
this macro.

I'm not sure that I fully understand the inquiry/discussion. An
implementation doesn't have to use 'sizeof (int)' bytes at any time
during evaluation, as far as I know.

If you wish to reinterpret an object representation as another type,
unions are handy.

union char_and_int {
unsigned char bytes[sizeof (int)];
char c;
int i;
};

/* First member 'bytes' initialized to zero bytes */
union char_and_int foo = { { 0 } };

/* Member 'c' set to '5' */
foo.c = 5;
/* Now you can work with 'foo.i' */

(But 'foo.i' might be a trap representation.)
 
S

Shao Miller

If you wish to reinterpret an object representation as another type,
unions are handy.

union char_and_int {
unsigned char bytes[sizeof (int)];
char c;
int i;
};

/* First member 'bytes' initialized to zero bytes */
union char_and_int foo = { { 0 } };

/* Member 'c' set to '5' */
foo.c = 5;
/* Now you can work with 'foo.i' */

(But 'foo.i' might be a trap representation.)

I should add that 'foo.i' isn't necessarily '5', either.
 
E

Eric Sosman

C allows type casting in which a variable is converted from one type
to another.

No. C allows casting (not "type casting") in which a value
(not a "variable") is converted from one type to another.
Does C (whatever standard) allow the type of a variable to change,
within a statement, avoiding the conversion? And if so, provide an
example of how its done.

Every C expression has a type, determined at compile time and
immutable thereafter. A variable (in suitable context) is an
expression, albeit a rather simple one. A variable, once declared,
has an immutable type and there's nothing you can do to change it
short of editing the source code.
Example:
int a=23;
int b=34;
char c='a';
int * p_int=(int *)&c;

// type casting
// c is converted into type integer, then b is added.
(int) c + b;

The *value* of `c' is converted to the type int and then
the value of `b' is added. `c' is still of type `char'.
//retypeing
(type int) c + b;
// similar action
*p_int + b

Sorry; I'm unable to fathom your meaning here.
Ignoring alignment issues, storage size issues, etc., c is retyped to
an integer, no conversion is done, and c is used, within the
statement, as an integer, not a char.

Ditto.
 
E

Eric Sosman

As everyone pointed out, "converted" should be "promoted", and "during
evaluation" should have been tacked on the end. That would have helped
on the semantics of the question, but is still vague.

Still wrong, too. Promotions are a subset of conversions, not a
superset. Some conversions performed by casts are not promotions at
all: `(short)42' for example.
Exactly. The pomotion happens according to the standard, but only the
value of c is used, and because c is type char, 1 byte.

I see no promotions at all in `(int)c + b'. There is an explicit
conversion of the value of `c' to type `int', and the addition of the
value of `b' (also of type `int', in the snippage). On an "exotic"
system with CHAR_MAX > INT_MAX, the char-to-int conversion could in
fact be a "demotion."
I don't have a way to define it. But the point is IF c could be "retyped"
to an int, then sizeof(int) bytes would be used during evaluation. As
other posters pointed out, there would be alignment issues, unknown bytes
at&c+1 to&c+sizeof(int), etc...

Your intent is still unclear to me, but I begin to suspect you
have confused representation with value. C doesn't compute with
bytes and bits, but with the values those bytes and bits represent.
You may think a `char' is eight bits, but how wide is it when it's
been loaded into a 64-bit CPU register? The value is what matters.

(Usually, at any rate, and certainly in the examples you've
shown. Representation arises in a few cases: For example, it is
always permitted to manipulate an object's storage as an array of
bytes. For operators like `+' and `(type)' it's all about value.)
 
R

Rich Touper

Still wrong, too. Promotions are a subset of conversions, not a
superset. Some conversions performed by casts are not promotions at
all: `(short)42' for example.


I see no promotions at all in `(int)c + b'. There is an explicit
conversion of the value of `c' to type `int', and the addition of the
value of `b' (also of type `int', in the snippage). On an "exotic"
system with CHAR_MAX > INT_MAX, the char-to-int conversion could in fact
be a "demotion."

The range of bytes would be (assuming sizeof(int)>1) &c+1 thru
&c+(sizeof(int)-1).

Those bytes, if even allocated in storage, within a valid address
range, and/or at valid addresses, would be dependent on the machine
endianess and/or architecture.
Your intent is still unclear to me, but I begin to suspect you
have confused representation with value. C doesn't compute with bytes
and bits, but with the values those bytes and bits represent. You may
think a `char' is eight bits, but how wide is it when it's been loaded
into a 64-bit CPU register? The value is what matters.

(Usually, at any rate, and certainly in the examples you've
shown. Representation arises in a few cases: For example, it is always
permitted to manipulate an object's storage as an array of bytes. For
operators like `+' and `(type)' it's all about value.)

Similar to casting, "retyping" would allow subterfuge and introduce
opportunity for non portable code (as in this example). Only persons
integrating non portable assembly and C code would probably find it
useful (expecially with mmx instructions). Still, thought I'd ask. And
thanks for the conversion lecture.
 

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,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top