0

The code demo below works but I'm not sure it's syntactically correct.

For example, should this

X = *((QWORD*)(pRegCtx->X));

be replaced with

X = *(QWORD*)(pRegCtx->X);

Plus code looks odd using a QWORD cast

RegisterContext RegCtx = { (QWORD)&X };

Without the (QWORD) cast, the linux c compiler reports:

warning: initialization of ‘long unsigned int’ from ‘QWORD *’ {aka ‘long unsigned int *’} makes integer from pointer without a cast [-Wint-conversion]

Any tips on how make it conform better to the C89 standard?

https://www.onlinegdb.com/0pBta5XO2

#include <stdio.h>
#include <stdint.h>

typedef         uint64_t QWORD;
typedef         uint32_t DWORD;
typedef         uint16_t WORD;
typedef         uint8_t  BYTE;

typedef struct  RegisterContext
{
          QWORD X;
} RegisterContext, *PREGISTERCONTEXT;


void MyFun(PREGISTERCONTEXT pRegCtx)
{
     QWORD X = 0;
     X = *((QWORD*)(pRegCtx->X));
     X += 42;
     *((QWORD*)(pRegCtx->X)) = X;
 } 

int main(void)
{    
         QWORD X = 0;
         RegisterContext RegCtx = { (QWORD)&X };
   
         MyFun(&RegCtx);
         
         // Answer to the Ultimate Question of Life, the Universe, and Everything
         printf("X=%lu\n",X);

    return 0;
}
2
  • Why are you trying to store a pointer to a QWORD as a QWORD in the struct? Commented Jan 26, 2022 at 0:29
  • 1
    X = *((QWORD*)(pRegCtx->X)); and X = *(QWORD*)(pRegCtx->X); are semantically equivalent, so I don’t understand what the question is there. Commented Jan 26, 2022 at 0:50

1 Answer 1

1
  1. Never hide pointers and arrays behind typedefs.
  2. Use standard int types instead of QWORD and similar. There is no reason to introduce new strange types.
  3. Use correct printf formats.
  4. Do not overcomplicate simple things.
typedef struct  RegisterContext
{
          uint64_t X;
} RegisterContext;


void MyFun(RegisterContext *pRegCtx)
{
     uint64_t X = 0;
     X = pRegCtx->X;
     X += 42;
     pRegCtx->X = X;
 } 

int main(void)
{    
    uint64_t X = 0;
    RegisterContext RegCtx = { X };
   
     MyFun(&RegCtx);
         
     X = RegCtx.X;
      
     printf("X=%"PRIu64"\n", RegCtx.X);

     return 0;
}

https://godbolt.org/z/noPW46W3r

If your structure represents the layout of the hardware register mapped into the address space then you need to use macros.

typedef struct  RegisterContext
{
      uint64_t X;
      uint64_t Y;
      uint64_t Z;
      uint64_t W;
} RegisterContext;


#define REG1ADDRESS 0x40000340

#define REG1 ((volatile RegisterContext*)REG1ADDRESS)


void setX(void)  
{
    REG1 -> Z = 0x45654564;
}
Sign up to request clarification or add additional context in comments.

4 Comments

Very clean! Although running it gave main.c:27:22: error: expected ‘)’ before ‘PRIu64’.
@vengy you need to #include <inttypes.h>
From an efficiency standpoint though, there's an extra X = RegCtx.X; versus directly updating the variable itself. This struct has 1 element but in production has 7 so I really need performant code. Thanks!
Thanks for these ideas and I appreciate your time!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.