user3591723
user3591723

Reputation: 1284

Why is 1 byte being displayed as if it were 4 in this code?

I am trying to write my C socket code in Assembly (just kinda bored and thought it'd be an interesting exercise) and in the process of trying to make the sockaddr_in struct I wrote this little program:

#include <stdio.h>
#include <string.h>
#include <netinet/in.h>

void showbytes(char *c, size_t len) {
    size_t i;
    for (i = 0; i < len; i++)
        printf("byte #%lu -> %x\n", i, c[i]);
}

int main(int argc, char* argv[]) {
    struct sockaddr_in q;

    bzero(&q, sizeof(q));

    q.sin_family = 0x02;
    q.sin_port = htons(0x1f90);
    q.sin_addr.s_addr = htonl(INADDR_ANY);

    union {
        struct sockaddr_in sai;
        char c[sizeof(struct sockaddr_in)];
    } un;
    un.sai = q;
    showbytes(un.c, sizeof(struct sockaddr_in));

    return 0;
}

What I don't understand at all is that the output looks like this:

byte #0 -> 2
byte #1 -> 0
byte #2 -> 1f
byte #3 -> ffffff90
byte #4 -> 0
byte #5 -> 0
byte #6 -> 0
byte #7 -> 0
byte #8 -> 0
byte #9 -> 0
byte #10 -> 0
byte #11 -> 0
byte #12 -> 0
byte #13 -> 0
byte #14 -> 0
byte #15 -> 0

Why is byte #3 showing as 4 bytes? I checked sizeof(in_port_t) and it is definitely 2 bytes, but that isn't even the issue. A char should only ever be 1 byte.. I assume I am missing something pretty big here.

Upvotes: 2

Views: 73

Answers (1)

Jens
Jens

Reputation: 72639

You are missing that char is signed on your implementation and a negative value, interpreted as an unsigned int (for %x), is a large value. You may also be missing that you can't pass a one byte value to a variadic function like printf--integral values are always promoted to at least int or unsigned int.

If you compile with gcc or clang, use -funsigned-char to make the char type unsigned. Then this problem does not occur.

Upvotes: 4

Related Questions