Home > Software design >  Change address of variable
Change address of variable

Time:07-18

What I've tried:

Main.h

#pragma once

union TBufferRec
{
    int ID;
};
extern TBufferRec BufferRec;

Main.cpp

#include "Main.h"

void MovePointer(void* PPointer)
{
    static_cast<TBufferRec*>(*BufferRec) = static_cast<TBufferRec*>(PPointer);
}

Errors:

E0349 no operator "*" matches these operands

C2679 binary '=': no operator found which takes a right-hand operand of type 'TBufferRec *' (or there is no acceptable conversion)

How can I make BufferRec point to a new address?

SOLVED:

Very informative feedback, thank you.

Main.h

#pragma once

union TBufferRec
{
    int ID;
};
extern union TBufferRec* BufferRec;
extern void MovePointer(void* PPointer);

Main.cpp

#include "Main.h"

TBufferRec* BufferRec;

void MovePointer(void* PPointer)
{
    BufferRec = static_cast<TBufferRec*>(PPointer);
}

CodePudding user response:

Let's do it step by step, solving one problem at a time and building upon previous solituons.

Suppose you have two pointers to TBufferRec objects, how to assign one object to the other? Given a pointer, you access the pointed-to object by dereferencing (the unary asterisk operator).

void assign0(TBufferRec* lhs, TBufferRec* rhs) {
   *lhs = *rhs;
}

OK now one of the pointers is still pointing to a TBufferRec, but has type void*, what to do? You convert a pointer of one type to a pointer of another type by casting.

void assign1(TBufferRec* lhs, void* rhs) {
   assign0(lhs, static_cast<TBufferRec*>(rhs));
   // or the same as
   // *lhs = *static_cast<TBufferRec*>(rhs);
}

OK now instead of a pointer, you have an actual variable, what to do? Given a variable, you obtain a pointer to it by using the address-of operator (the unary ampersand, the opposite of dereferencing)

void assign2(void* rhs) {
   extern TBufferRec lhs;
   assign1(&lhs, rhs);
   // or the same as
   // assign0(&lhs, static_cast<TBufferRec*>(rhs));
   // or the same as
   // *(&lhs) = *static_cast<TBufferRec*>(rhs);
   // or the same as
   // lhs = *static_cast<TBufferRec*>(rhs);
}

CodePudding user response:

extern TBufferRec BufferRec;

This means that BufferRec is union TBufferRec.

The function make no sense. I'll explain what every part does:

void MovePointer(void* PPointer)

The function receives pointer to void (some kind of generic pointer)

static_cast<TBufferRec*>(PPointer);

PPointer is casted to be a pointer to TBufferRec

(*BufferRec)

You can't do this. You go to the value which the pointer BufferRec is pointing to, but, BufferRec isn't a pointer, it is a union. You probably meant to write:

static_cast<TBufferRec*>(&BufferRec) = static_cast<TBufferRec*>(PPointer);

But this also make no sense because you cast pointer to TBufferRec to be pointer to TBufferRec. So what you really meant to do is to make the BufferRec a pointer and in addition, not to cast it:

   extern TBufferRec BufferRec;
void MovePointer(void* PPointer)
{
    static_cast<TBufferRec*>(*BufferRec) = static_cast<TBufferRec*>(PPointer);
}

When you use extern it means that it this variable should be allocated in another file without extern (you must understand extern before using it).

CodePudding user response:

I have to assign one union variable to another through pointers/addresses.

void AssignByPointer(TBufferRec *lhs, const TBufferRec *rhs) {
    *lhs = *rhs;
}

AssignByPointer(&BufferRec, &LocalBufferRec);

// or simpler without pointers/addresses
BufferRec = LocalBufferRec;

CodePudding user response:

Reading your comments and particularly the one replying to Ziv Kvatinsky I think you've misunderstood what extern does.

This:

extern TBufferRec BufferRec;

declares to the compiler that BufferRec is defined in another source file and during the link phase will be resolved to a definition of the symbol. If it isn't exactly one definition there'll be an error (Symbol not found or duplicate Symbol found).

That has nothing to do with whether you can change the address of BufferRec at run-time and because it's declared as an object (albeit in another source file) you can't.

You can't change the address of a variable at run-time. You can change variables that are addresses (called pointers). It may help to re-read that a couple of times.

So, I'm not sure what you're doing but it would make more sense to declare a variable that is an address (a pointer) since you appear to want to specify where data is at run-time.

extern TBufferRec* BufferRecPointer; 

in your Main.h and

TBufferRec* BufferRecPointer;

void MovePointer(TBufferRec &BufferRec)
{
    BufferRecPointer=&BufferRec;
}

in your Main.cpp.

I don't know what you've got going on with the void * but it looks like something that will blow up in your face.

void MovePointer(void *PPointer){
    BufferRecPointer=static_cast<TBufferRec*>(PPointer);
}

would mean the compiler will let you pass practically any pointer to MovePointer and have it treated (elsewhere in your program - unshown) as a valid location to store a non-trivial object of type TBufferRec both size, alignment and non-trivial initialisation of the std::sting member will almost certainly cause issues if not handled correctly.

  •  Tags:  
  • c
  • Related