C/C++ hasn't been my primary programming language in recent years and the strict aliasing issue has evaded me. I not sure if I understood it correctly. There are plenty of standard C functions which have void * parameters, such as memset, memcpy, read, write, etc. Does the strict aliasing rule mean the code below is not valid any more?

The objection I see to this, compared to the template version, is that you always have to cast (as you did in the last line) unless you happen to be sending a byte pointer. As is explained the C++ FAQ, "casts are evil" however sometimes they are a necessary evil. If you can code in a way that minimizes the number of casts you are reducing the evil.

I haven't addressed the question about the void pointer, yet ...

Please post technical questions on the forum, not by personal message. Thanks!

The memcpy function takes void* arguments, meaning that no assumptions are made about what is being pointed to; no aliasing has occurred here. In contrast, *(unsigned*)&p interprets a pointer to void* as a pointer to unsigned, which is aliasing.

If I understand correctly (and I'm not sure I do) the anti-aliasing rule is supposed to stop you casting a type to void and then to another type, in some sort of "trickiness" that may or may not work in a particular implementation and endianness.

(edit) In particular, it might confuse compiler optimization.

However a function like memcpy, or malloc, isn't trying to cast (say) char to int, it's trying to return (or copy) a block of memory of any type.

Disclaimer: I might be wrong about this.

Please post technical questions on the forum, not by personal message. Thanks!

The other objection to this, compared to the template version, is that it relies on you correctly sending down the size (sizeof(MyInt)) whereas the template version gets the size itself, reducing the chance for error (eg. during copy/paste).

Please post technical questions on the forum, not by personal message. Thanks!

Thanks Nick, I can see your point, especially on sending down the size. On the other hand, using templates makes the sketch bigger (consumes more of the precious flash memory) and people with C background are already used to functions like memset() and read() which use the same calling convention as my version of sendAnything(). I don't think that either of the alternatives is absolutely better.

Even if I send two different type (int and float) the templated version still is 6 bytes shorter. Of course, if you were sending dozens of types of data (would you actually do that?) then the pointer version would use less program memory.

Test on a Uno with 1.0.1.

Please post technical questions on the forum, not by personal message. Thanks!

Even if I send two different type (int and float) the templated version still is 6 bytes shorter. Of course, if you were sending dozens of types of data (would you actually do that?) then the pointer version would use less program memory.

Test on a Uno with 1.0.1.

I though that the whole point of using templates or generic pointer types was the function will be used to send objects of several types (definitely more than two). If that wasn't the case, instead of sendAnything(), I could have as well have implemented sendMyInt() and sendMyFloat() or overloaded send(MyInt &data) and send(MyFloat &data).

And I'll guess that the memory consumption also depends on how complicated (or big) the function body is. sendAnything() was trivial. If the function's body is bigger then the overhead in the template alternative starts to pile up sooner.

With "common implementation merging" in the linker, template functions that have the same actual bytecode (because they serialize values of the same size, say,) will all use the same "actual" function under the hood, leading to less bloat. The "pointer and size" function doesn't have any bloat in implementation, but instead there's a little bit of bloat each time you call it, as the size has to be passed as an argument, not hard-coded in the function.

If size REALLY matters, you have to implement it both ways and measure it :-)

With "common implementation merging" in the linker, template functions that have the same actual bytecode (because they serialize values of the same size, say,) will all use the same "actual" function under the hood, leading to less bloat. The "pointer and size" function doesn't have any bloat in implementation, but instead there's a little bit of bloat each time you call it, as the size has to be passed as an argument, not hard-coded in the function.

If size REALLY matters, you have to implement it both ways and measure it :-)

I've read that size always matters, but then again this is a family oriented site so I will leave it at that.

If the code for all data types effectively just works out the size and address of the memory occupied by the data, it makes no odds which approach you take and could even be reduced to a macro. The important thing in my mind is whether you expect to ever need to apply this function to something where the decision about which bytes to serialise needs to be type-specific. For example, to serialise a string value it would be sensible to measure the string length rather than just output the pointer, or the first char pointed to. When exporting a struct or class that contains pointers, it might be necessary to do a deep copy rather than a shallow one. Same for any other non-trivial data structures.

However, if you're mainly interested in coping with primitive variables that have different sizes, all those considerations are irrelevant.

I only provide help via the forum - please do not contact me for private consultancy.

Nick has provided very convincing arguments for using templates. One more question still. The OP's requirements were:

Quote

I want a function that I can pass either a string of characters or an integer or an object ..

He probably expects to send the strings without terminating zeros. The code below won't probably work with the template version of sendAnything, will it? Can sendAnything be fixed to work with strings as well?