Assigning an array to another array using C's assignment operator


M

Myth__Buster

Hi,

Here is one technique I have thought of to allow the assignment of
one array to another in an indirect manner as it's not allowed
directly in C. Before all, I would like to clarify that it's not
something designed to replace memcpy(). It's a technique to
illustrate that how good C's rich set of operators are. So, have a
look and tell me what you think of it. The code has all the
reasoning for the different operators I have used. Hope they make
things straightforward.

Cheers,
Raghavan

<code>
#include <stdio.h>
// Applicable for arrays which are allocated dynamically also!
//
// The struct assignment below might result in the same code
// as it would if you happened to use memcpy() and the like.
// But, the purpose here is different!
//
// Purpose here is - To show that "C" indirectly allows array
// to array assignment. :)
//
// NOTE: The struct built for this suffers from no padding
// issues whatsoever since it involves just an array which
// must be contiguous and hence the compiler is forced not
// to play with it even if it wants to for whatever reasons!
//
// This macro doesn't check for the size of the
// destination and hence the user of this macro should
// take care of it.
//
// Why the use of comma-expression seemingly dummy
// one? Well, it is needed to inform the compiler that
// we are not punning the types but sincerely dealing
// with the given addresses to just copy data of the
// given size.
//
// Why seemingly useless (void *) casting? Well, again
// to inform the compiler that we are punning types as
// said earlier and this cast is required for
// convincing strict-aliasing=1.
//
// And why (void) casting in that comma expression?
// Well, it is to inform the compiler that we
// understand and hence ignore the value of it manually,
// for having no effect.
//
// The previous attempt would fail to compile if the
// size-based macro is used more than once in the same
// scope. So, I have used __LINE__ macro to build the
// unique data type in this attempt.
//
// Well, the user of this technique can build the
// required data type with unique name by himself/herself
// very easily. But, to ease his/her job a little, I am
// constructing the required unique data type with the
// help of the macro. And the uniqueness is based on the
// line number at which this macro gets placed. So, there
// will be a redefinition of a specific struct type if
// you happen to use this macro more than once in the
// same line. However, this limitation shouldn't be the
// reason not to use this technique which you can as well
// use directly by building the struct type by yourself
// in your code wherever you want.
//
#define AssignArraysLine(dest, src, line) \
( \
*(struct t##line \
{ \
char arr[ sizeof(src) ]; \
} *) ((void)dest, (void *)dest)\
= \
*(struct t##line *) \
((void)src, (void *)src) \
)
#define AssignArraysOfSizeLine(dest, src, size, line) \
( \
*(struct t##line \
{ \
char arr[ size ]; \
} *) ((void)dest, (void *)dest)\
= \
*(struct t##line *) \
((void)src, (void *)src) \
)
#define DummyMacro1(b, a, line) AssignArraysLine(b, a, line)
#define DummyMacro2(b, a, size, line) \
AssignArraysOfSizeLine(b, a, size, line)
// Don't get misled by the term static here in the below
// macro. It's just to signify that it's meant for only
// arrays defined using C array subscript([]) operator,
// which includes variable length arrays.
//
// NOTE : Don't use the macro more than once in the
// same line of your source as __LINE__ will be same
// and hence you would get type-redefinition error.
//
// And macros are known for side-effects, so be wary
// of them or you can just hand-code the comprehensive
// typecasting the above macro does without any
// problem - you can just ignore __LINE__ macro as
// well if you code by hand since you will not
// deliberately redefine a struct more than once!
#define AssignStaticArrays(b, a) DummyMacro1(b, a, __LINE__)
// Universal macro - works for all types of arrays.
//
// NOTE : Don't use the macro more than once in the same
// line of your source as __LINE__ will be same and hence
// you would get type-redefinition error.
//
// And macros are known for side-effects, so be wary of
// them or you can just hand-code the comprehensive
// typecasting the above macro does without any problem -
// you can just ignore __LINE__ macro as well if you code
// by hand since you will not deliberately redefine a
// struct more than once!
#define AssignArraysOfSize(b, a, size) \
DummyMacro2(b, a, size, __LINE__)
int main(void)
{
int a[ 10 ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int b[ sizeof(a) ];
int i = 0;
printf("Array a : ");
while ( i < 10 )
{
printf("%d ", a[ i ]);
i++;
}
printf("\n");
AssignStaticArrays(b, a); // Once more in the
// same line -
// AssignStaticArrays(b, a);
// - Nope!
i = 0;
printf("Array b : ");
while ( i < 10 )
{
printf("%d ", b[ i ]);
i++;
}
printf("\n");
int z[ sizeof(a) ];
AssignStaticArrays(z, a); // This works as it's on a
// different line from the
// previous usage above!
i = 0;
printf("Array z : ");
while ( i < 10 )
{
printf("%d ", z[ i ]);
i++;
}
printf("\n");
int c[ sizeof(a) ];
AssignArraysOfSize(c, a, sizeof(a)); // Same rules
// apply to this
// macro usage
// as well as
// above.
i = 0;
printf("Array c : ");
while ( i < 10 )
{
printf("%d ", b[ i ]);
i++;
}
printf("\n");
int d[ sizeof(c) ];
AssignArraysOfSize(d, c, sizeof(c)); // Works as it's
// on a different
// line.
i = 0;
printf("Array d : ");
while ( i < 10 )
{
printf("%d ", d[ i ]);
i++;
}
printf("\n");
return 0;
}

</code>
 
Ad

Advertisements

M

Myth__Buster

Hi,

Here is one technique I have thought of to allow the assignment of
one array to another in an indirect manner as it's not allowed
directly in C. Before all, I would like to clarify that it's not
something designed to replace memcpy(). It's a technique to
illustrate that how good C's rich set of operators are. So, have a
look and tell me what you think of it. The code has all the
reasoning for the different operators I have used. Hope they make
things straightforward.

Cheers,
Raghavan

<code>
#include <stdio.h>
// Applicable for arrays which are allocated dynamically also!
//
// The struct assignment below might result in the same code
// as it would if you happened to use memcpy() and the like.
// But, the purpose here is different!
//
// Purpose here is - To show that "C" indirectly allows array
// to array assignment. :)
//
// NOTE: The struct built for this suffers from no padding
// issues whatsoever since it involves just an array which
// must be contiguous and hence the compiler is forced not
// to play with it even if it wants to for whatever reasons!
//
//       This macro doesn't check for the size of the
//       destination and hence the user of this macro should
//       take care of it.
//
//       Why the use of comma-expression seemingly dummy
//       one? Well, it is needed to inform the compiler that
//       we are not punning the types but sincerely dealing
//       with the given addresses to just copy data of the
//       given size.
//
//       Why seemingly useless (void *) casting? Well, again
//       to inform the compiler that we are punning types as
//       said earlier and this cast is required for
//       convincing strict-aliasing=1.
//
//       And why (void) casting in that comma expression?
//       Well, it is to inform the compiler that we
//       understand and hence ignore the value of it manually,
//       for having no effect.
//
//       The previous attempt would fail to compile if the
//       size-based macro is used more than once in the same
//       scope. So, I have used __LINE__ macro to build the
//       unique data type in this attempt.
//
//       Well, the user of this technique can build the
//       required data type with unique name by himself/herself
//       very easily. But, to ease his/her job a little, I am
//       constructing the required unique data type with the
//       help of the macro. And the uniqueness is based on the
//       line number at which this macro gets placed. So, there
//       will be a redefinition of a specific struct type if
//       you happen to use this macro more than once in the
//       same line. However, this limitation shouldn't be the
//       reason not to use this technique which you can as well
//       use directly by building the struct type by yourself
//       in your code wherever you want.
//
#define AssignArraysLine(dest, src, line)               \
                        (                              \
                         *(struct t##line               \
                         {                              \
                             char arr[ sizeof(src) ];   \
                         } *) ((void)dest, (void *)dest)\
                                          =             \
                         *(struct t##line *)            \
                              ((void)src, (void *)src)  \
                        )
#define AssignArraysOfSizeLine(dest, src, size, line)   \
                        (                              \
                         *(struct t##line               \
                         {                              \
                             char arr[ size];          \
                         } *) ((void)dest, (void *)dest)\
                                          =             \
                         *(struct t##line *)            \
                              ((void)src, (void *)src)  \
                        )
#define DummyMacro1(b, a, line) AssignArraysLine(b, a, line)
#define DummyMacro2(b, a, size, line) \
                    AssignArraysOfSizeLine(b, a, size, line)
// Don't get misled by the term static here in the below
// macro. It's just to signify that it's meant for only
// arrays defined using C array subscript([]) operator,
// which includes variable length arrays.
//
// NOTE : Don't use the macro more than once in the
// same line of your source as __LINE__ will be same
// and hence you would get type-redefinition error.
//
// And macros are known for side-effects, so be wary
// of them or you can just hand-code the comprehensive
// typecasting the above macro does without any
// problem - you can just ignore __LINE__ macro as
// well if you code by hand since you will not
// deliberately redefine a struct more than once!
#define AssignStaticArrays(b, a) DummyMacro1(b, a, __LINE__)
// Universal macro - works for all types of arrays.
//
// NOTE : Don't use the macro more than once in the same
// line of your source as __LINE__ will be same and hence
// you would get type-redefinition error.
//
// And macros are known for side-effects, so be wary of
// them or you can just hand-code the comprehensive
// typecasting the above macro does without any problem -
// you can just ignore __LINE__ macro as well if you code
// by hand since you will not deliberately redefine a
// struct more than once!
#define AssignArraysOfSize(b, a, size) \
                        DummyMacro2(b, a, size, __LINE__)
int main(void)
{
    int a[ 10 ] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int b[ sizeof(a) ];
    int i = 0;
    printf("Array a : ");
    while ( i < 10 )
    {
          printf("%d ", a[ i ]);
          i++;
    }
    printf("\n");
    AssignStaticArrays(b, a); // Once more in the
                              // same line -
                              // AssignStaticArrays(b, a);
                              // - Nope!
    i = 0;
    printf("Array b : ");
    while ( i < 10 )
    {
          printf("%d ", b[ i ]);
          i++;
    }
    printf("\n");
    int z[ sizeof(a) ];
    AssignStaticArrays(z, a); // This works as it's on a
                              // different line from the
                              // previous usage above!
    i = 0;
    printf("Array z : ");
    while ( i < 10 )
    {
          printf("%d ", z[ i ]);
          i++;
    }
    printf("\n");
    int c[ sizeof(a) ];
    AssignArraysOfSize(c, a, sizeof(a)); // Same rules
                                         // apply to this
                                         // macro usage
                                         // as well as
                                         // above.
    i = 0;
    printf("Array c : ");
    while ( i < 10 )
    {
          printf("%d ", b[ i ]);
          i++;
    }
    printf("\n");
    int d[ sizeof(c) ];
    AssignArraysOfSize(d, c, sizeof(c)); // Works as it's
                                         // on a different
                                         // line.
    i = 0;
    printf("Array d : ");
    while ( i < 10 )
    {
          printf("%d ", d[ i ]);
          i++;
    }
    printf("\n");
    return 0;

}

</code>

Typo fix :
// Why seemingly useless (void *) casting? Well, again
// to inform the compiler that we are punning types as
// said earlier and this cast is required for
// convincing strict-aliasing=1.

Should be
// Why seemingly useless (void *) casting? Well, again
// to inform the compiler that we are *NOT* punning types as
// said earlier and this cast is required for
// convincing strict-aliasing=1.
 

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

Top