3

When compiling the following code :

struct Point {
    int x;
    int y;
};
struct Position {
    int x;
    int y;
};
struct Point p = {1, 2};
struct Position q = (struct Position)p;

An error occurs :

error: used type 'struct Position' where arithmetic or pointer type is required

Isn't there some way to cast between different struct instances when those struct actually have the same definition ?

Weier
  • 1,339
  • 1
  • 10
  • 20
  • 1
    Throught pointers: struct Position * q = (struct Position* )&p; – Shaggi Nov 23 '13 at 19:30
  • 1
    @Shaggi while that would "work", that wouldn't be different *instances*. A dereference and proper lvalue would make that what the OP is looking for (no comment on whether its a good idea). – WhozCraig Nov 23 '13 at 19:35
  • @WhozCraig Yea you're right he needed different instances :) just move the asterisk as shown in the other answers... – Shaggi Nov 23 '13 at 20:50

4 Answers4

4

There's no such thing as "cast" for struct types in C language. C language only supports casts for scalar types and void.

When any other type is used inside (), it is no longer a cast. It can only be valid as a part of compound literal syntax. Compound literals is a completely different feature of C language, not related to any casts. For example, this would be correct

struct Position q = (struct Position) { 1, 2 };

In your case you apparently need a reinterperting sequence

q = *(struct Position *) &p;

C language states that this sort of access is considered valid, as long as your struct declarations are indeed synchronized. You can also consider simply memcpy-ing one object to the other.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
3

You can do this using type punning, since the standard permits that two structures sharing a common initial sequence be aliased as long as only the common initial members are accessed:

struct Position q = *(struct Position *)&p;

or even better

union {
    struct Position pos;
    struct Point pt;
} pun;

pun.pt = p;
struct Position q = pun.pos;
  • I will up vote this quickly if you can remind me that it is *allowable* to use a union member that was *not* the most recently assigned lvalue as an expression rvalue. My brain is in lockdown since my recent work project finally shipped, so forgive me if I'm slipping, or if that restriction is in C++ and not C. – WhozCraig Nov 23 '13 at 19:41
  • @WhozCraig Exactly, that's C++'s restriction. C99 (not C89, though) explicitly permits type punning through unions. –  Nov 23 '13 at 19:42
  • Thanks. I like the second snippet just for the creative nuance if that is the case. – WhozCraig Nov 23 '13 at 19:43
  • 1
    @WhozCraig I've proposed using a union because generally that's the approach without UB. (For a less standard-freak person, it can be quite confusing when it is or it isn't allowed to alias through a pointer of different type, but using a union is never UB in simple cases according to C99.) –  Nov 23 '13 at 19:47
1

Casting one C structure into another

I think this has the answer.

Check this also

Is it possible to cast struct to another?

Although you can cast almost anything to anything, doing it with structures is error-prone.

You could use a pointer to do the typecast;

Point_var = *((point *) &position_var);

Community
  • 1
  • 1
Rafed Nole
  • 112
  • 1
  • 4
  • 16
0

You cannot do direct typecasting, but you can achieve this using pointer typecasting as follows -

struct Point *p;
p->x=1;
p->y=2;
struct Position *q = (Position *)p;
theharshest
  • 7,767
  • 11
  • 41
  • 51
  • 2
    note that -- as written -- this is undefined behavior, and most likely a crash, because you're dereferencing an uninitialized pointer. – user4815162342 Nov 23 '13 at 19:35
  • 1
    Apart from being undefined behavior by dereferencing an indeterminate pointer, this isn't different instances, rather it is a pointer alias to the *same* instance. – WhozCraig Nov 23 '13 at 19:36