I have this code:
typedef struct {
int test;
} SensorData_t;
volatile SensorData_t sensorData[10];
SensorData_t getNextSensorData(int i)
{
SensorData_t data = sensorData[i];
return data;
}
int main(int argc, char** argv) {
}
It compiles with gcc version 8.3, but not with g . Error message:
main.c: In function ‘SensorData_t getNextSensorData(int)’:
main.c:8:34: error: no matching function for call to ‘SensorData_t(volatile SensorData_t&)’
SensorData_t data = sensorData[i];
^
main.c:3:3: note: candidate: ‘constexpr SensorData_t::SensorData_t(const SensorData_t&)’ <near match>
} SensorData_t;
^~~~~~~~~~~~
main.c:3:3: note: conversion of argument 1 would be ill-formed:
main.c:8:34: error: binding reference of type ‘const SensorData_t&’ to ‘volatile SensorData_t’ discards qualifiers
SensorData_t data = sensorData[i];
~~~~~~~~~~~~^
main.c:3:3: note: candidate: ‘constexpr SensorData_t::SensorData_t(SensorData_t&&)’ <near match>
} SensorData_t;
^~~~~~~~~~~~
main.c:3:3: note: conversion of argument 1 would be ill-formed:
main.c:8:34: error: cannot bind rvalue reference of type ‘SensorData_t&&’ to lvalue of type ‘volatile SensorData_t’
SensorData_t data = sensorData[i];
I'm not sure if I need to add volatile as well for the data
variable and the return type, shouldn't be needed because it is copied. But I do access the sensorData array from an interrupt as well (on an embedded system), so I think I need volatile
for the top level variable sensorData.
CodePudding user response:
Your program is trying to copy a SensorData_t
object. The compiler supplies a copy constructor with the following signature:
SensorData_t(const SensorData_t &)
This copy constructor will not work with volatile
arguments, hence the compilation error.
You can write your own copy constructor which works with volatile
SensorData_t
objects (as well as non-volatile
SensorData_t
objects):
struct SensorData_t {
SensorData_t() = default;
SensorData_t(const volatile SensorData_t &other)
: test(other.test) {
}
int test;
};
CodePudding user response:
As an alternative to the accepted answer, you may consider avoid copying the data from the array altogether, if the getNextSensorData
is a simple getter function for the global sensorData
:
// Intorduce type alias
using SD = const volatile SensorData_t&;
SD getNextSensorData(int i)
{
return sensorData[i];
}
This way (if it is suitable for the design), you'll keep the definitions code more concise. But I have to note that the usage is a bit less direct than in the copy case:
int main() {
// Type alias
SD sd1 = getNextSensorData(0);
// Deduced type
auto&& sd2 = getNextSensorData(1);
// Explicit type
const volatile SensorData_t& sd3 = getNextSensorData(2);
}