Four variables share one string?

N

Nephi Immortal

Is there a way how to create ONE four bytes in memory storage and
four variables can access one str directly? I can do that without
static const and C++ Compiler will be able to compile without any
problem, but static is disallowed in union.
I do not want to use pointer variable to str because I prefer “direct
memory” variable instead of “indirect memory” variable.

union
{
static const char str[ 5 ] = “ABCD”;
struct Letter
{
static const char a;
static const char b;
static const char c;
static const char d;
} letter;
};

char A = letter.a; // read A from str and put it in A variable
char B = letter.b; // read A from str and put it in B variable
char C = letter.c; // read A from str and put it in C variable
char D = letter.d; // read A from str and put it in D variable
 
V

Victor Bazarov

Is there a way how to create ONE four bytes in memory storage and
four variables can access one str directly? I can do that without
static const and C++ Compiler will be able to compile without any
problem, but static is disallowed in union.
I do not want to use pointer variable to str because I prefer “direct
memory†variable instead of “indirect memory†variable.

union
{
static const char str[ 5 ] = “ABCDâ€;
struct Letter
{
static const char a;
static const char b;
static const char c;
static const char d;
} letter;
};

char A = letter.a; // read A from str and put it in A variable
char B = letter.b; // read A from str and put it in B variable
char C = letter.c; // read A from str and put it in C variable
char D = letter.d; // read A from str and put it in D variable

You could try

struct Foo {
static const char str[5]; // initialization has to be outside
static const char &a;
static const char &b;
static const char &c;
static const char &d;
};

const char Foo::str[] = { "ABCD" };
const char &Foo::a = Foo::str[0];
const char &Foo::b = Foo::str[1];
const char &Foo::c = Foo::str[2];
const char &Foo::d = Foo::str[3];

V
 
N

Nephi Immortal

   Is there a way how to create ONE four bytes in memory storage and
four variables can access one str directly?  I can do that without
static const and C++ Compiler will be able to compile without any
problem, but static is disallowed in union.
   I do not want to use pointer variable to str because I prefer “direct
memory” variable instead of “indirect memory” variable.
union
{
   static const char str[ 5 ] = “ABCD”;
   struct Letter
   {
           static const char a;
           static const char b;
           static const char c;
           static const char d;
   } letter;
};
   char A = letter.a; // read A from str and put it in A variable
   char B = letter.b; // read A from str and put it in B variable
   char C = letter.c; // read A from str and put it in C variable
   char D = letter.d; // read A from str and put it in D variable

You could try

    struct Foo {
        static const char str[5]; // initialization has to be outside
        static const char &a;
        static const char &b;
        static const char &c;
        static const char &d;
    };

    const char Foo::str[] = { "ABCD" };
    const char &Foo::a = Foo::str[0];
    const char &Foo::b = Foo::str[1];
    const char &Foo::c = Foo::str[2];
    const char &Foo::d = Foo::str[3];

str variable is direct memory address. It requires only one x86
instruction. If you choose to use reference or pointer, both
reference and pointer are just the same because it is indirect memory
address and requires two x86 instructions.
Unfortunately, four reference variables require additional 16 bytes
while str array holds only four bytes plus one byte as null
terminator.
union is only the option to allow one four bytes while five variables
share one memory space.
If you only use one variable as str[ x ], you actually don’t know
what individual character represents is for?

char a = str[ 0 ]; // don’t know what str[ 0 ] is
char b = str[ 1 ]; // don’t know what str[ 1 ] is

With union, you know what it is:

char a = letter_A;
char b = letter_B;

Perhaps enum is helpful.

enum
{
letter_A,
letter_B,
letter_C,
letter_D
};

char a = str[ letter_A ]; // know what str[ 0 ] is
char b = str[ letter_B ]; // know what str[ 1 ] is

enum has four constants and require additional 16 bytes.
Do you have idea if there is another way how to overcome union to
accept const instead of static const?

Keep in touch – Merry Christmas!! Smile…
 
K

Kalle Olavi Niemitalo

Nephi Immortal said:
enum has four constants and require additional 16 bytes.

Usually not true. In typical implementations of C++ (and C),
if you compile

enum { zero, one, two, three };
int f(const int p[])
{
return p[two] - p[three];
}

the generated code and data are the same as if you had compiled

int f(const int p[])
{
return p[2] - p[3];
}

i.e. the enum type does not take up space in the executable
program. It does take up space in debug information, symbol
tables, and such; but if you are compiling for a device with so
little memory that you need to worry about 16 bytes, then you
probably will not install those things into the device anyway.
Do you have idea if there is another way how to overcome union to
accept const instead of static const?

If the union does not need to be anonymous, you can do this:

static const union
{
char str[ 5 ];
struct Letter
{
char a;
char b;
char c;
char d;
} letter;
} u = {"ABCD"};

int main()
{
char A = u.letter.a; // read 'A' from str and put it in A variable
char B = u.letter.b; // read 'B' from str and put it in B variable
char C = u.letter.c; // read 'C' from str and put it in C variable
char D = u.letter.d; // read 'D' from str and put it in D variable
}
 
V

Victor Bazarov

Nephi Immortal said:
enum has four constants and require additional 16 bytes.

Usually not true. In typical implementations of C++ (and C),
if you compile

enum { zero, one, two, three };
int f(const int p[])
{
return p[two] - p[three];
}

the generated code and data are the same as if you had compiled

int f(const int p[])
{
return p[2] - p[3];
}

i.e. the enum type does not take up space in the executable
program. It does take up space in debug information, symbol
tables, and such; but if you are compiling for a device with so
little memory that you need to worry about 16 bytes, then you
probably will not install those things into the device anyway.
Do you have idea if there is another way how to overcome union to
accept const instead of static const?

If the union does not need to be anonymous, you can do this:

static const union
{
char str[ 5 ];
struct Letter
{
char a;
char b;
char c;
char d;
} letter;
} u = {"ABCD"};

int main()
{
char A = u.letter.a; // read 'A' from str and put it in A variable
char B = u.letter.b; // read 'B' from str and put it in B variable
char C = u.letter.c; // read 'C' from str and put it in C variable
char D = u.letter.d; // read 'D' from str and put it in D variable
}

Strictly speaking, the point of unions is to share the memory, the
ability to store something, BUT NOT the value of it. The 2003 Standard
still allowed to read only the value that was put in the union, but
never write one part and read another. That actually has undefined
behavior. I don't know whether that was relaxed in C++11.

V
 
M

Michael DOUBEZ

Usually not true.  In typical implementations of C++ (and C),
if you compile
enum { zero, one, two, three };
int f(const int p[])
{
         return p[two] - p[three];
}
the generated code and data are the same as if you had compiled
int f(const int p[])
{
         return p[2] - p[3];
}
i.e. the enum type does not take up space in the executable
program.  It does take up space in debug information, symbol
tables, and such; but if you are compiling for a device with so
little memory that you need to worry about 16 bytes, then you
probably will not install those things into the device anyway.
If the union does not need to be anonymous, you can do this:
static const union
{
   char str[ 5 ];
   struct Letter
   {
           char a;
           char b;
           char c;
           char d;
   } letter;
} u = {"ABCD"};
int main()
{
   char A = u.letter.a; // read 'A' from str and put it in A variable
   char B = u.letter.b; // read 'B' from str and put it in B variable
   char C = u.letter.c; // read 'C' from str and put it in C variable
   char D = u.letter.d; // read 'D' from str and put it in D variable
}

Strictly speaking, the point of unions is to share the memory, the
ability to store something, BUT NOT the value of it.  The 2003 Standard
still allowed to read only the value that was put in the union, but
never write one part and read another.  That actually has undefined
behavior.  I don't know whether that was relaxed in C++11.

Actually, you can if they are POD and have a common initial sequence
(see §9.5/1).

Now, we could argue that in the example 'str' and 'Letter' have a
common initial sequence of four char. Perhaps strictly speaking not
layout compatible but they are actually both aggregates of char.
 
N

Nephi Immortal

Usually not true.  In typical implementations of C++ (and C),
if you compile
enum { zero, one, two, three };
int f(const int p[])
{
         return p[two] - p[three];
}
the generated code and data are the same as if you had compiled
int f(const int p[])
{
         return p[2] - p[3];
}
i.e. the enum type does not take up space in the executable
program.  It does take up space in debug information, symbol
tables, and such; but if you are compiling for a device with so
little memory that you need to worry about 16 bytes, then you
probably will not install those things into the device anyway.
If the union does not need to be anonymous, you can do this:
static const union
{
   char str[ 5 ];
   struct Letter
   {
           char a;
           char b;
           char c;
           char d;
   } letter;
} u = {"ABCD"};
int main()
{
   char A = u.letter.a; // read 'A' from str and put it in A variable
   char B = u.letter.b; // read 'B' from str and put it in B variable
   char C = u.letter.c; // read 'C' from str and put it in C variable
   char D = u.letter.d; // read 'D' from str and put it in D variable
}

Strictly speaking, the point of unions is to share the memory, the
ability to store something, BUT NOT the value of it.  The 2003 Standard
still allowed to read only the value that was put in the union, but
never write one part and read another.  That actually has undefined
behavior.  I don't know whether that was relaxed in C++11.

However, all five variables share the same memory address as long as
you can do read only AND read/write only. Think of two pointers
below.

char arraySector[ 4096 ];

char* beginArraySector = &arraySector[ 0 ];
char* endArraySector = &arraySector[ 4096 - 1 ];

const char* cBeginArraySector = &arraySector[ 0 ];
const char* cEndArraySector = &arraySector[ 4096 - 1 ];

*( beginArraySector + 100 ) = ‘A’; // read/write only
*( endArraySector - 1000 ) = ‘Z’; // read/write only

char A = *( cBeginArraySector + 100 ); // read only
char B = *( cEndArraySector - 1000 ); // read only

I choose to use union instead of pointer and/or reference because I
want to use direct memory and not indirect memory. Another folk
already answered the question. I am satisfied.
 
V

Victor Bazarov

Nephi Immortal<[email protected]> writes:
enum has four constants and require additional 16 bytes.
Usually not true. In typical implementations of C++ (and C),
if you compile
enum { zero, one, two, three };
int f(const int p[])
{
return p[two] - p[three];
}
the generated code and data are the same as if you had compiled
int f(const int p[])
{
return p[2] - p[3];
}
i.e. the enum type does not take up space in the executable
program. It does take up space in debug information, symbol
tables, and such; but if you are compiling for a device with so
little memory that you need to worry about 16 bytes, then you
probably will not install those things into the device anyway.
Do you have idea if there is another way how to overcome union to
accept const instead of static const?
If the union does not need to be anonymous, you can do this:
static const union
{
char str[ 5 ];
struct Letter
{
char a;
char b;
char c;
char d;
} letter;
} u = {"ABCD"};
int main()
{
char A = u.letter.a; // read 'A' from str and put it in A variable
char B = u.letter.b; // read 'B' from str and put it in B variable
char C = u.letter.c; // read 'C' from str and put it in C variable
char D = u.letter.d; // read 'D' from str and put it in D variable
}

Strictly speaking, the point of unions is to share the memory, the
ability to store something, BUT NOT the value of it. The 2003 Standard
still allowed to read only the value that was put in the union, but
never write one part and read another. That actually has undefined
behavior. I don't know whether that was relaxed in C++11.

However, all five variables share the same memory address as long as
you can do read only AND read/write only.[..]

If you write one member of the union, any attempt to read another member
of the union has undefined behavior, unless they are both POD and share
the same layout. See Michael's post explaining that you *might* still
be OK if we somehow consider that four 'char' members of your 'struct
Letter' have the _same layout_ as the five-element array or char.

Whatever tricks you want to play with addresses is system-, compiler-
and platform-specific, and any use of it is at the risk of the one who
uses it, the *Standard* does not specify any behavior for it. That's all.

V
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top