3

関数に uint8_t として渡す必要がある float 変数があります。

float 元の値に戻すにはどうすればよいですか。

コード:

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);
}

uint8_t 配列から float の元の値を取得しようとしており、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));

私は常に値を 0 として取得します。

助けてください

4

2 に答える 2

7

コードに未定義の動作があります。Afloatは通常 4 バイト長uint8_tですが、 は 1 バイトです。したがって、配列を少なくとも 3 バイトで上書きします。

次にGetLoopOutMessage、実際の配列 (2 バイト) のみを渡すと、浮動小数点数のデータの大部分が失われます。

たとえば、使用したい場合があります

uint8_t args[1 + sizeof(float)];

GetLoopOutMessage渡されたデータがコピーされない場合は、未定義の動作の別のケースがあります。つまり、ローカル変数へのポインターを渡します。関数が戻ると、SetAnalogローカル変数が格納されているメモリ内のスペースは、次の関数呼び出しで再利用されます。これは、args配列がメモリ内に存在しなくなり、以前は存在していた場所に別のデータが存在する可能性があることを意味します。

これを解決するには、args配列staticを作成するか、グローバルにするか (実際にはお勧めしません)、ヒープに動的に割り当てる必要があります。

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

delete使い終わったら (つまり、データを取得したとき)、このポインターを忘れないでください。

于 2013-09-04T12:57:50.007 に答える
0

次のようにしてみてください。

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

次に、次のように渡します。

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

そして、次のようにデータを読み取ります。

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;

コールバックでデータを使用しているように見えるため、ローカルスタックストレージではなくnew/ hereを使用したことに注意してください。そのため、データを読み取る前にデータが上書きされた(たまたまゼロで)と推測していますdelete.


new/deleteが不適切な場合(GetLoopOutMessageデータのコピーを作成する)、次のようにします。

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

次に、次のように渡します。

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

そして、次のようにデータを読み取ります。

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 に答える