3

I have a float variable , which needs to be passed as uint8_t to the function .

How do I convert back to float original value .

Code:

bool SetAnalog(uint8_t number, float voltage, MessagePriority priority, Callback clbck)
{
    uint8_t args[2];
    args[0] = number;
    memcpy(&(args[1]),&voltage,sizeof(float));

    PTCLoopOutMessage* message = parent()->GetLoopOutMessage(this,
                                                             this->address(),
                                                             _OutputVoltage,
                                                             "DACVoltage",
                                                             args,
                                                             sizeof(args),
                                                             Device,
                                                             priority);
    message->SetCallback(clbck);

    return ProcessOutMessage(message);
}

I try to get back the float original value from uint8_t array and need to assign to probe[channel]

uint8_t channel = message->GetOutMessage()->GetData()->data[0];
unsigned char* value = &message->GetOutMessage()->GetData()->data[1];
memcpy(&__output.output.probe[channel].dac, value, sizeof(float));

I always get value as 0,

Please Help

4

2 回答 2

7

You have undefined behavior in your code. A float is normally four bytes long, while uint8_t is a single byte. So you overwrite your array with at least three bytes.

Then when you pass it in the GetLoopOutMessage you only pass the actual array (which is two bytes), so the floating point number is now missing the majority of its data.

You might want to use e.g.

uint8_t args[1 + sizeof(float)];

If the GetLoopOutMessage doesn't copy the data you pass to it, then you have another case of undefined behavior, namely passing around a pointer to a local variable. When the SetAnalog function returns, the space in memory where local variables are stored is reused by the next function call. This means that the args array no longer exists in memory, and where it used to be there may now be other data.

To solve this you either should make the args array static, make it global (really not recommended) or to dynamically allocate it on the heap:

uint8_t* args = new uint8_t[1 + sizeof(float)];

Don't forget to delete this pointer once your done with it (i.e. when you retrieved the data).

于 2013-09-04T12:57:50.007 回答
0

Try it like this:

struct MyArgs {
  uint8_t channel;
  float voltage;
} *args = new MyArgs();
args->channel = number;
args->voltage = voltage;

Then pass it like this:

....GetLoopOutMessage(....., (uint8_t *)args, sizeof(*args), ....)

And read the data out like this:

struct MyArgs {
  uint8_t channel;
  float voltage;
} *args = (struct MyArgs *)message->GetOutMessage()->GetData()->data;

uint8_t channel = args->channel;
__output.output.probe[channel].dac = args->voltage;

delete args;

Note that I've used new/delete here, not local stack storage, because you appear to be using the data in a callback, so I'm guessing your data has been overwritten (with zero, as it happens) before you get to read it.


If new/delete is inappropriate (GetLoopOutMessage makes a copy of the data), then do it like this:

struct {
  uint8_t channel;
  float voltage;
} args = {number, voltage};

Then pass it like this:

....GetLoopOutMessage(....., (uint8_t *)&args, sizeof(args), ....)

And read the data out like this:

struct mydata {
  uint8_t channel;
  float voltage;
} *args = (struct mydata *)message->GetOutMessage()->GetData()->data;

uint8_t channel = args->channel;
__output.output.probe[channel].dac = args->voltage;
于 2013-09-04T13:30:56.353 回答