0

I am using sscanf to put a MAC address from a string into a uint8 array. For some reason, the uint8 array is all blank.

#include <iostream>
#include <string.h>
using namespace std;

int main()
{
    std::string mac = "00:00:00:00:00:00";
    uint8_t smac[7];
    memset(smac, 0, 7);
    sscanf(
        mac.c_str(), 
        "%hhu:%hhu:%hhu:%hhu:%hhu:%hhu",
        &smac[0],
        &smac[1],
        &smac[2],
        &smac[3],
        &smac[4],
        &smac[5]
    );

    std::cout << "string: " << mac << std::endl;
    std::cout << "uint8_t: "<< smac;

    return 0;
}
S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
errno_44
  • 151
  • 6
  • Does this answer your question? [uint8\_t can't be printed with cout](https://stackoverflow.com/questions/19562103/uint8-t-cant-be-printed-with-cout) – UnholySheep Dec 17 '19 at 17:56
  • @UnholySheep This is printing an array of `uint8_t`s. It's similar, but not the same question. – S.S. Anne Dec 17 '19 at 17:56
  • I think the `sscanf` format string is laughing at us. It has good reason to. The result code is being ignored. – user4581301 Dec 17 '19 at 17:59
  • Is not the `stdio.h` header necessary to incorporate `sscanf()`? – RobertS supports Monica Cellio Dec 17 '19 at 18:02
  • @user4581301 Can you elaborate on that? I don't see anything wrong. You may be confusing `sscanf` with `scanf`. – S.S. Anne Dec 17 '19 at 18:03
  • 1
    @RobertS-ReinstateMonica `iostream` probably has `#include ` and `using namespace std;` pulls `std::sscanf` into the global namespace. – S.S. Anne Dec 17 '19 at 18:04
  • 1
    @JL2210 that was just me saying that the return code has been left unchecked in too many words. The "hhu hhu hhu hhu hhu hhu" format string reminds me of Jabba the Hutt laughing. – user4581301 Dec 17 '19 at 18:40
  • Note that MAC addresses express their numbers in hexidecimal, not decimal. So you would need to use `%hhx` of `%hhX` instead of `%hhu`. You should also check the return value of `sscanf()` to make sure it is returning 6 – Remy Lebeau Dec 17 '19 at 21:42

2 Answers2

3

uint8_t is on most platforms a typedef for unsigned char. Therefore, cout is trying to print it as a string, but it encounters a null byte (or string terminator) as the first character, so it stops printing.

A solution here would be to print all the MAC address members individually:

for(int c = 0; c < sizeof(smac); c++)
{
    std::cout << +smac[c];
    if(c != sizeof(smac) - 1)
        std::cout << "::";
}
std::cout << '\n';

The + here performs integer promotion so smac[c] will be printed as a number and not a character.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
  • 1
    Thanks - my real issue is that I still get all `0`s. If my mac is "FF:FF..." it's still all 0s. – errno_44 Dec 17 '19 at 18:05
  • 3
    @errno_44 Well, you're inputting zeros and expecting... not zeros? I mean, `"00:00:00:00:00:00"` looks like all zeros to me. – S.S. Anne Dec 17 '19 at 18:06
2

The types uint8_t and unsigned char are generally equivalent to the compiler. The convention for outputting an array of char (unsigned or not) is to stop when you reach a value of zero, because that indicates the end of the string.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622