Canbus is a pipe where you dump messages. The interpretation of the payload of the messages is up to each node. In a custom system, where all nodes run code you control, you're the boss as to what bits go into any message.
Is it commonly used to send and receive float value over CANBUS?
Sure! It's rather convenient, because most sensible MCU platforms use IEEE-754 float representation, and if you're using them in one project then likely they have same endianness too. So you can send C float fields as raw data by memcpy-ing them from a float field into the send buffer on the transmit side, and then memcpy-ing them back from the send buffer into a float field. Modern compilers (e.g. gcc used for ARM) optimize small memcpy into small inline assembly code.
memcpy is then not a literal function call, but telling the compiler "hey, I want to move some bytes of data from here to there, figure it out". memcpy's semantics are important in this respect. There are other ways of "moving data around" using pointer arithmetic and whatnot, and they often are undefined behavior if the type of the data changes. So memcpy is a good choice, at least for a beginner not deep into the semantics of C or C++ (they differ a lot too!).
The classic CAN frame has room for up to 8 bytes of payload. So you can stick one 64-bit double or two 32-bit floats in a CAN frame.
Note: Some C platforms have same size for
double datatypes - this is allowed by the standard. But all IEEE-754 platforms have
float being exactly 4 bytes long, and that should be plenty of resolution for temperature measurements in typical automotive environments.
And you can always make sure - by adding a static assert in the code, so that the compiler will complain if assertions are false:
static_assert(sizeof(float) == 4, "This program needs a 32-bit float type to work");
Static assertions can be inside functions our outside of them in global scope. They'll work the same, since they have no runtime effect. They just help avoid mistakes/problems that the compiler is able to statically detect. Compile-time errors are much easier to figure out than runtime errors :)