This is the archetypal problem with benchmarks: not only are they hard to design, but people will incorrectly nit-pick the results.
You count the number of allocations, without looking at the big picture: this is a toy example. It provides the hard-coded input to the function. This results in the C version not having to allocate memory for the hard-coded literals and the function problably being inlined and optimized away and the strlen() calls being equally optimized away as the length of the strings are known at compile time.
In the real world, these would come from some input where they would need to be allocated on the heap, just like the C++ version does. It would use just as many allocations, except they will all be hand-rolled, hand-held, error-prone, with every bit of memory management explicit. C++ is superior in every measure here. Only in toy programs and hard-coded strings does C wins.
If the goal was to have as few allocations from hard-coded strings, then just write "foo@bar" and avoid the concatenation altogether. That is not the point of the example.
(Also, the newer C++ standard support std::string literals, FWIW.)