0

I have the following code for Arduino (C++). This is for a checksum consisting of 2 characters forming a base 16 value between 0 and 255. It takes int outputCheckSum and converts it to char outputCheckSumHex[3].

itoa (outputCheckSum, outputCheckSumHex, 16)
  if (outputCheckSum < 16) { //Adds a 0 if CS has fewer than 2 numbers
    outputCheckSumHex[1] = outputCheckSumHex[0];  
    outputCheckSumHex[0] = '0';
  }

Since the output of itoa would be "X" instead of "0X" in the event of X having fewer than 2 characters, the last 3 lines are to move the characters one step back.

I now have plans to scale this up to a CS of 8 characters, and I was wondering whether there exists a function in C++ that can achieve that before I start writing more code. Please let me know if more information is required.

HFOrangefish
  • 267
  • 1
  • 10

2 Answers2

3

You should be able to use memmove, it's one of the legacy C functions rather than C++ but it's available in the latter (in cstring header) and handles overlapping memory correctly, unlike memcpy.

So, for example, you could use:

char buff[5] = {'a', 'b', 'c', '.', '.'};
memmove(&(buff[2]), &(buff[0], 3);
// Now it's {'a', 'b', 'a', 'b', 'c'} and you can replace the first two characters.

Alternatively, you could use std::copy from the algorithm header but, for something this basic, memmove should be fine.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 3
    C++ has std::copy which will have an optimized implementation and is more typesafe – Pepijn Kramer Oct 04 '22 at 12:49
  • 1
    @PepijnKramer, you should be wary of blanket statements like "will have an optimised implementation", it's by no means guaranteed. In any case, `memmove()` is probably also likely to be optimised and is perfectly adequate for character handling such as requested here. – paxdiablo Oct 04 '22 at 12:56
  • 2
    @PepijnKramer There's exactly zero difference between type safeness between the two when copying char arrays - which is what OP asked for. Granted, we wouldn't move smart pointers and lock around like this - but that's not what OP asked for. Specific question, specific answer. – lorro Oct 04 '22 at 13:14
  • 1
    Related: [Is it better to use std::memcpy() or std::copy() in terms to performance?](https://stackoverflow.com/q/4707012/3212865) (despite the name answers go beyond pure performance aspect). The TLDR: there is absolutely no reason to use `memcpy` / `memmove` except old habits. – spectras Oct 04 '22 at 13:24
  • @paxdiablo It is not a blanket statment. std::copy has a performance benefit (vectorizing compilers). Try it in compiler explorer :) – Pepijn Kramer Oct 04 '22 at 15:11
  • @PepijnKramer: if you'd like to point out the part of ISO C++ that states it *must* be vectorised, I'd be happy to concur. I couldn't find it myself :-) It has mandated performance characteristics like "exactly N assignments" but any _decent_ `memmove` would also have that characteristic. And, in fact, it could use fewer assignments in the byte case since it could choose to assign multiple bytes at once. Now `std::copy` _may_ also be able to do that but I think it would probably require a specialised template and I'm not convinced that wouldn't violate the "exactly N" mandate in the standard. – paxdiablo Oct 05 '22 at 04:31
1

You can use memmove in <cstring> for this. It does not check for terminating null characters, but instead copies num bytes (third argument) and works with overlapping regions as well.

void* memmove(void* destination, const void* source, size_t num);
lorro
  • 10,687
  • 23
  • 36
  • 2
    No those functions have more of a place in "C" then "C++" just use std::copy. Anything with void* is a code smell (in C++). – Pepijn Kramer Oct 04 '22 at 12:50
  • 2
    @PepijnKramer We don't agree on this one. The fact that is takes `void*` is to be able to work with any POD type. It does exactly what OP requires and is part of the standard, so I don't understand the downvote, either. – lorro Oct 04 '22 at 13:13
  • Related: [Is it better to use std::memcpy() or std::copy() in terms to performance?](https://stackoverflow.com/q/4707012/3212865) (despite the name answers go beyond pure performance aspect). The TLDR: there is absolutely no reason to use `memcpy` / `memmove` except old habits. – spectras Oct 04 '22 at 13:22
  • @lorro I can agree to disagree :) But for me the fact is that void* breaks typesafety. And in all my years of development I find that the typesafety is a very important feature of any development environment and specially C++. It allows the compiler to catch bugs before they happen. For example it is one of the reasons I always model options as enums and not as bools, they are semantically different and types allow you to model that semantic difference. (And yes I do go one step beyond asking OP question directly with that) – Pepijn Kramer Oct 04 '22 at 14:02