shengy shengy - 15 days ago 4
C Question

How can I do a structure type conversion like this?

say if I have two structure types:

typedef struct
{
unsigned int * a;
char * b;
char * c;
}TYPEA;

typedef struct
{
unsigned int * a;
unsigned int * b;
}TYPEB;


And I also have a pointer array, which contains pointer pointing to
TYPEA
types:

TYPEA* AArray[1] =
{
&ga,
};


ga
is defined as:

TYPEA ga =
{
&num1,
&b,
&c,
};


If I have another
TYPEA
var defined, I can modify
AArray[0]
's content's value, like this:

TYPEA another_ga =
{
&num3,
&b,
&c,
};

void change_AArray()
{
*AArray[0] = another_ga;
}


This works perfectly good, but the question is, as
TYPEA
and
TYPEB
's first 32bits are same(Both are
unsigned int
) is it possible for me to change
AArray
's
ga
's content to a
TYPEB
structure?

Here are my attempts:

void change_AArray()
{
/* *AArray[0] = another_ga; */

/* Compile Error */
/* *AArray[0] = gb; */

/* Compile Error */
/* *AArray[0] = (TYPEA)gb; */

/* Passed compile, but AArray[0] is not changed */
/* AArray[0] = (TYPEA*)&gb; */
}


I then tried to add another pointer and put it in
AArray[0]
instead of using
&ga
, but it can't pass compile stage, I think C is requiring a constant in the initialize list.

TYPEA * pga = &ga;
TYPEA* AArray[1] =
{
pga, // error, needs a constant expression.
};
void change_AArray()
{
AArray[0] = (TYPEA*)&gb;
}


Is it possible to do the type conversion?

The entire code:

#include <stdio.h>

typedef struct
{
unsigned int * a;
char * b;
char * c;
}TYPEA;

typedef struct
{
unsigned int * a;
unsigned int * b;
}TYPEB;

int num1 = 10, num2 = 20, num3 = 30;
char b = 'b', c = 'c';

TYPEA ga =
{
&num1,
&b,
&c,
};

TYPEA another_ga =
{
&num3,
&b,
&c,
};

TYPEB gb =
{
&num2,
&num3,
};

TYPEA* AArray[1] =
{
&ga,
};

void change_AArray()
{
*AArray[0] = another_ga;
/* How can I do this conversion? */
/* *AArray[0] = gb; */
}

int main(int argc, const char *argv[])
{
printf("ga.a: %d\n", *ga.a);
printf("gb.b: %d\n", *gb.a);

change_AArray();

printf("After calling change_AArray()\n");
printf("ga.a: %d\n", *ga.a);
printf("gb.b: %d\n", *gb.a);

return 0;
}

Answer
void change_AArray()
{   
   *AArray[0] = *((TYPEA*) &gb);  //#1
   /* error:
   *(AArray[0]) = (TYPEA) gb;     //#2
   */
}

You can use #1 for your purpose.

If use #2, gcc reports an error:
error: conversion to non-scalar type requested

Questions are:
- What's scalar/non-scalar type?
- What does this error message mean?
- Why #2 fails?

What's scalar/non-scalar type?
int, char, pointers are scalar type, and a structure is not.
See details here,http://herbert.the-little-red-haired-girl.org/en/prgmsc1/docs/part2a.pdf

What does this error message mean?
If you do assignment between scalar and non-scalar type, you'll get this error.

Why #2 fails?
For *(AArray[0]) = (TYPEA) gb;, both sides are non-scalar types. So, it looks like it shouldn't get the above error.
However, C doesn't allow cast between structures. See http://msdn.microsoft.com/en-us/library/d9f2bsy2.aspx.

A test program,

struct a{ int i;};
struct b{ int i; };

int main (int argc, char *argv[])
{
    struct a aaa;
    struct b bbb;
    bbb = (struct b)aaa;

    return 0;
}

gcc reports an error: error: conversion to non-scalar type requested

So to conclude, the reason for failure of #2 is that C language doesn't allow cast between structures.