0

I'm trying to create some variables within certain structs, and I need to create a function that would reset all the values in the namespace to 0. I'm aware I can just tediously reset them all to 0 one by one, but I'm certain that's not the best way to do it. Another question I want to ask is that is it alright to initialise all the variables as undefined/NULL? Would that cause any bottlenecks in my code at compile time?

namespace REGISTER {
    struct GPR {
        // 64-bit
        struct R64 {
            uint64_t RAX; // accumulator
            uint64_t RBX; // base
            uint64_t RCX; // counter
            uint64_t RDX; // data
            uint64_t RSP; // stack pointer
            uint64_t RBP; // stack base pointer
            uint64_t RSI; // source index
            uint64_t RDI; // destination index
        } R64;

        // 32-bit
        struct R32 {
            uint32_t EAX;
            uint32_t EBX;
            uint32_t ECX;
            uint32_t EDX;
            uint32_t ESP;
            uint32_t EBP;
            uint32_t ESI;
            uint32_t EDI;
        } R32;

        // 16-bit
        struct R16 {
            uint16_t AX;
            uint16_t BX;
            uint16_t CX;
            uint16_t DX;
            uint16_t SP;
            uint16_t BP;
            uint16_t SI;
            uint16_t DI;
        } R16;

        // 8-bit
        struct R8 {
            uint8_t AH;
            uint8_t BH;
            uint8_t CH;
            uint8_t DH;
            uint8_t AL;
            uint8_t BL;
            uint8_t CL;
            uint8_t DL;

            uint8_t SPL;
            uint8_t BPL;
            uint8_t SIL;
            uint8_t DIL;
        } R8;
    } GPR;

    // Segment registers
    struct SREG {
        uint16_t SS; // stack
        uint16_t CS; // code
        uint16_t DS; // data
        uint16_t ES; // extra data
        uint16_t FS; // more extra data
        uint16_t GS; // still more extra data
    } SREG;

    // Pointer registers
    struct PREG {
        uint64_t RIP;
        uint32_t EIP;
        uint16_t IP;
    } PREG;
};
Braiam
  • 1
  • 11
  • 47
  • 78
Existentialist
  • 177
  • 2
  • 9
  • 3
    If you are sure they're all POD types like numbers, why not `memset(&gprData, 0, sizeof(GPR));`? – Joe Mar 07 '22 at 20:25
  • Someone might tell me why this is wrong, but it looks like you can just `memset()` it. – sweenish Mar 07 '22 at 20:25
  • Are you wanting to clear out the whole namespace's worth of variables? – user4581301 Mar 07 '22 at 20:26
  • @user4581301 yep – Existentialist Mar 07 '22 at 20:27
  • @Existentialist `namespace` are neither objects nor containers of objects. It is not possible to get a list of objects in a `namespace`, neither can you get any kind of reference to their collective representation (it isn't like a big struct). You need to enumerate the objects you want to zero out explicitly at least once. Additionally, `} REGISTER'` is a syntax error. It looks like you are treating `namespace REGISTER` as if it was `struct REGISTER` which is not correct. You can't instantiate a `namespace`. – François Andrieux Mar 07 '22 at 20:29
  • `memset` will work here. – dmedine Mar 07 '22 at 20:29
  • Are you asking about resetting values for an existing instance of `GPR`, `SREG`, etc, or are you asking about specifying default values for all fields? – 0x5453 Mar 07 '22 at 20:30
  • You might have a case for an over-arching `struct REGISTER`, instead of the namespace, that you can zero with a single call. Otherwise the only ways I can think of to clear everything all at once are hide a bunch of individual sets for each of the variables in a function or abuse the out of undefined behaviour. – user4581301 Mar 07 '22 at 20:31
  • @0x5453 It's for resetting already existing values – Existentialist Mar 07 '22 at 20:34
  • 1
    Assigning empty braces will handle cases like "floating point zero is not all-bits-zero" or "nullptr is not all-bits zero". – Raymond Chen Mar 07 '22 at 20:35
  • @FrançoisAndrieux my bad, the whole namespace was previously a class and I switched it to a namespace but forgot about that last line of code. Thanks for pointing it out. – Existentialist Mar 07 '22 at 20:36

1 Answers1

3

I see you're getting some suggestions to use memset. I think that's a mistake. It might be perfectly fine with the data you have, but as soon as someone down the road adds a string to your class, suddenly that's bad.

I would give each of them a default value of zero and then use the assignment operator to a newly-constructed version.

It's good practice to automatically initialize all your values, anyway -- to 0 or nullptr or whatever makes sense. Leaving them undefined the way you have is a big opportunity for bugs.

So: GPR blank; *this = blank;

And you would be good to go.

Joseph Larson
  • 8,530
  • 1
  • 19
  • 36
  • `GPR blank = {};` should initialize `blank`, each member will be either initialized according to its member initializer or to zero if there isn't one. In OP's case, it will zero initialize all members. The last part of this answer doesn't require the first part. `*this = {};` should also work, in the context of a member function. – François Andrieux Mar 07 '22 at 20:58
  • I believe in C++11 only, this solution may break existing code as adding initializers to the struct may cause it to no longer be an aggregate type. This should be fixed in C++14 and member initializers didn't exist before C++11. – François Andrieux Mar 07 '22 at 21:03
  • @FrançoisAndrieux As he specified C++ and not an old version, I believe the convention here is to assume a relatively modern capabilities, but good points. – Joseph Larson Mar 07 '22 at 22:19