C - ntohl replacing digits with zero's - c

In the following program on Little and Big Endians:
char *s = "1234";
printf("%08X\n",*(int *)s); //big endian
int little = ntohl(*s);
printf("%08X\n",little);//Little endian
I get the following output:
34333231
31000000
The second line should be the reverse order of the first line. What am I doing wrong?
I have little experience in C, but some experience in other languages.

You need something like this:
int little = ntohl(*((uint32_t*)s));
otherwise you're only passing a char to ntohl, which is why your value is being truncated.

You are confusing strings and integers
uint32_t i = 12345;
printf("%08X\n", i); /* 00003039 */
i = ntohl(i);
printf("%08X\n", i); /* either 00003039 or 39300000 */
Depending on the endianness of your platform, you either get the same output or a bytewise reversed one.

Related

Converting a struct to a hex string in C

I have the following struct
typedef struct __attribute__((packed)) word {
uint16_t value;
uint8_t flag
} Word;
I want to convert it to a hex string. For example if value = 0xabcd and flag = 0x01 I want to get the string 01abcd
if I do some pointer juggling
Word word;
word.value = 0xabcd;
wordk.flag = 0x01;
printf("word: %X\n", *(int *)&word);
I get the output that I want (word: 1ABCD) but this doesn't seem safe
and when I tried to do this after looking at some of the answer here
char ptr[3];
memcpy(ptr, word, 3);
printf("word: %02X%02X%02X\n", ptr[2], ptr[1], ptr[0]);
I got word: 01FFFFFFABFFFFFFCD, for some reason the first two bytes are being extended to a full int
There's no real gain from messing around with pointers or type-punning, if all you want is to output the values of the two structure members. Just print them individually:
printf("word: %02x%04x\n", (unsigned int)word.flag, (unsigned int)word.value);
Use a simple sprintf to convert to a string:
int main(void)
{
Word v = { 0xabcd, 0x01 };
char s[10];
sprintf(s, "%02x%04x", v.flag, v.value);
puts(s);
}
I want to get the string 01abcd
So you want to print the binary representation of the struct on a little endian machine backwards. There's no obvious advantage of using sprintf for this apart from it being quick & dirty to implement.
If you want something with performance, then hacking this out manually isn't rocket science - simply iterate over the struct byte by byte and convert each nibble to the corresponding hex character:
void stringify (const uint8_t* data, size_t size, char* dst)
{
for(size_t i=0; i<size; i++)
{
uint8_t byte = data[size-i-1]; // read starting from the end of the data
dst[i*2] = "0123456789ABCDEF"[ byte >> 4 ]; // ms nibble
dst[i*2+1] = "0123456789ABCDEF"[ byte & 0xF ]; // ls nibble
}
dst[size*2] = '\0';
}
This will give "01ABCD" on a little endian machine and "01CDAB" on a big endian machine.
(Optionally add restrict to data and dst parameters but I doubt it will improve performance since the const correctness already blocks aliasing at some extent.)
Could join them mathematically first.
printf("word: %06lx\n", wordk.flag * 0x10000L + word.value);
Using long in case we are on a 16-bit int machine.

how to write a uint64_t to a char* buffer in C

So I am trying to write a uint64_t return address to a buffer and then verify that the correct return address got written to the correct spot. Here is my code.
uint64_t new_ret = ret - 8 - 32 - 32 - 1001 + (ret_buffer_offset + sizeof(shellcode));
printf("new_ret :%lu\n", new_ret);
snprintf(&buffer[ret_buffer_offset], 8, "%s", new_ret);
// debug code
char buffer_debug[10];
uint64_t* buffer_uint = (uint64_t*)buffer_debug;
bzero(buffer_debug, 10);
strncpy(buffer_debug, &buffer[ret_buffer_offset], 8);
uint64_t ret_debug = *buffer_uint;
printf("ret debug: %lu\n", ret_debug);
the two printfs should output the same thing, but the bottom printf outputs a very different number. I'm not sure if the way I'm writing to the buffer is wrong or if the way I'm getting the value back is wrong. What is the issue here?
Thanks
snprintf(&buffer[ret_buffer_offset], 8, "%s", new_ret);
buffer now contains the string representation of your original value (or at least the first 8 bytes of the string representation). Your code then takes the first 8 bytes of this string and interprets that binary sequence as if it was a uint64_t. Step through this chunk of code in a debugger and you'll see exactly where the value changes.
I'm not sure exactly what this code is trying to do, but it seems like it's doing more copying and conversion than necessary. If you have a pointer to where you want the value to go, you should be able to either do memcpy(ptr, &new_ret, sizeof(new_ret)) or possibly even *(uint64_t*)ptr = new_ret if your platform allows potentially-misaligned writes. To print out the value for debugging, you'd use printf("%"PRIu64, *(uint64_t*)ptr).
I like to use union, but if you make a char pointer (char*) to point to the address of uint64_t it will work.
Using pointer will be:
uint64_t new_ret = ret - 8 - 32 - 32 - 1001 + (ret_buffer_offset + sizeof(shellcode));
buffer = (char*) &new_ret;
Test the code below to use union and pointer:
#include <stdio.h>
#include <stdint.h>
int main(){
union {
uint64_t u64;
char str[8];
} handler;
handler.u64 = 65;
printf("Using union:\n");
printf(" uint64: %ld\n", handler.u64);
printf(" char*: %s\n", handler.str);
uint64_t u64 = 65;
char *str = (char*)&u64;
printf("Using pointer:\n");
printf(" uint64: %ld\n", u64);
printf(" char*: %s\n", str);
return 0;
}

How to fprintf properly on my character struct array that contains Hex byte characters

Here's my problem, I have a byte struct that looks like these:
struct machinecode{
char byte1[2];
char byte2[2];
char byte3[2];
char byte4[2];
char byte5[2];
char byte6[2];
char byte7[2];
char byte8[2];
char byte9[2];
};
struct machinecode WRITEME[500];
now, these collection of 2byte chars or strings are formatted in hex bytes that looks like these for example:
byte1 = "01"
byte2 = "C0"
char bytes are assigned like these:
...
char * returner
...
strncpy(WRITEME[index].byte1, "00", 2);
strncpy(WRITEME[index].byte2, returner, 2);
my printing code looks like these:
while(counter < max){
...
else if(prog_counter[counter2] == 2){
fprintf(w, ???, WRITEME[counter].byte1);
fprintf(w, ???, WRITEME[counter].byte2);
}
...
}
Now I wanted this to print string as hex bytes, what kind of formatting(???) do I need to use for fprintf? or do I need to convert this hex byte string first to int before fprinting them?
I tried "%x", "%X" but they doesn't work.
EDIT:
I would like to add that I'm making a .com executable file, so I need to print them as hex bytes.
Revised answer
You say "I'm making a .COM executable file so I need to print them as hex bytes". The immediate response is then "Why on earth are you converting the values into a pair of bytes in the first place?" You'll have to convert them back to a single byte and then write that byte using the %c notation. One way, probably not the best way, to do that is:
static const char hexits[] = "0123456789ABCDEF";
static inline int byte_from_hex(const char *hex)
{
assert(isxdigit(hex[0]) && isxdigit(hex[1]));
int b1 = strchr(hexits, toupper((unsigned char)hex[0])) - hexits;
int b2 = strchr(hexits, toupper((unsigned char)hex[1])) - hexits;
return b1 * 16 + b2;
}
fprintf(w, "%c", byte_from_hex(WRITEME[counter].byte1);
But it would be far simpler not to convert to a string in the first place.
Original answer
Because your data is not null terminated, you need to use a length in the conversion specifications, as specified in the fprintf() manual page:
%.2s
This means print at most 2 characters from the character array.
fprintf(w, "%.2s", WRITEME[counter].byte1);
This assumes you did something like:
WRITEME[counter].byte1[0] = '0';
WRITEME[counter].byte2[1] = '1';
or:
memmove(WRITEME[counter].byte1, "01", sizeof(WRITEME[counter].byte1);
or (as the comments showed you did):
strncpy(WRITEME[counter].byte1, "01", 2); // or sizeof(WRITEME[counter].byte1)
and that you did not do something like:
sprintf(WRITEME[counter].byte1, "%2X", byte_value);
and that you did not do something like:
strcpy(WRITEME[counter].byte1, "01");
Here's how I fix this.
First I used Jonathan's solution of using sscanf and printf.
Then I encountered a weird bug that puts random "0d" on my file.
The solution was to open and write the file in binary mode.
w = fopen( filename , "wb" );
Hope this helps other users in the future

sprintf is outputting some strange data

I am working an embedded project which involves reading/writing a struct into EEPROM. I am using sprintf to make it easy to display some debugging information.
There are two problems with this code for some reason. The first; sprintf is printing a very strange output. When I print 'addr++' it will follow a pattern '0, 1, 2, 3, 4, 32, ...' which doesn't make sense.
void ee_read(char * buf, unsigned int addr, unsigned int len) {
unsigned int i;
sprintf(bf1, "Starting EEPROM read of %u bytes.\r\n", len); // Debug output
debugr(bf1);
IdleI2C1();
StartI2C1();
WriteI2C1(EE_ADDR | EE_W);
IdleI2C1();
WriteI2C1((unsigned char)addr>>8); // Address to start reading data from
IdleI2C1();
WriteI2C1((unsigned char)addr&0xFF);
IdleI2C1();
RestartI2C1();
WriteI2C1(EE_ADDR | EE_R);
IdleI2C1();
for (i=0; i<len; i++) {
buf[i] = ReadI2C1(); // Read a byte from EEPROM
sprintf(bf1, "Addr: %u Byte: %c\r\n", addr, buf[i]); // Display the read byte and the address
debugr(bf1);
addr++; // Increment address
IdleI2C1();
if (i == len-1) { // This makes sure the last byte gets 'nAcked'
NotAckI2C1();
} else {
AckI2C1();
}
}
StopI2C1();
}
The output from the above is here: https://gist.github.com/3803316 Please note that the about output was taken with %x for the address value (so addr is hex)
The second problem, which you may have noticed with the output, is that it doesn't stop when i > len. It continues further than the output I have supplied, and doesn't stop until the microcontroller's watch dog restarts.
Edit:
Calling the function
Location loc;
ee_read(&loc, 0, sizeof(Location));
Declarations:
struct location_struct {
char lat[12]; // ddmm.mmmmmm
char latd[2]; // n/s
char lon[13]; // dddmm.mmmmmm
char lond[2]; // e/w
char utc[11]; // hhmmss.sss
char fix[2]; // a/v
};
typedef struct location_struct Location;
char bf1[BUFFER_SIZE];
I don't think it's a race condition. I disable the interrupts which use bf1. Even then, it would corrupt the whole debug string if that happened, and it certainly wouldn't be so repeatable.
Edit
The value of addr starts as zero, which can be seen here: https://gist.github.com/3803411
Edit
What this is supposed to do it copy the location structure byte by byte into the EEPROM, and then recall it when it is needed.
Closure
So I never did solve this problem. The project moved away from the EEPROM, and I have since changed OS, compiler and IDE. It's unlikely I will replicate this problem.
I'll tell you one thing wrong with your code, this line:
(unsigned char)addr>>8
doesn't do what you seem to need.
It converts the value in addr into an unsigned char which (assuming 8-bit char and either 16-bit int or only using the lower 16 bits of a wider int), will will always give you the lower eight bits.
If you then right shift that by eight bits, you'll always end up with zero.
If your intent is to get the upper eight bits of the address, you need to use:
(unsigned char)(addr>>8)
so that the shift is done first.

C Programming: Convert Hex Int to Char*

My question is how I would go about converting something like:
int i = 0x11111111;
to a character pointer? I tried using the itoa() function but it gave me a floating-point exception.
itoa is non-standard. Stay away.
One possibility is to use sprintf and the proper format specifier for hexa i.e. x and do:
char str[ BIG_ENOUGH + 1 ];
sprintf(str,"%x",value);
However, the problem with this computing the size of the value array. You have to do with some guesses and FAQ 12.21 is a good starting point.
The number of characters required to represent a number in any base b can be approximated by the following formula:
⌈logb(n + 1)⌉
Add a couple more to hold the 0x, if need be, and then your BIG_ENOUGH is ready.
char buffer[20];
Then:
sprintf(buffer, "%x", i);
Or:
itoa(i, buffer, 16);
Character pointer to buffer can be buffer itself (but it is const) or other variable:
char *p = buffer;
Using the sprintf() function to convert an integer to hexadecimal should accomplish your task.
Here is an example:
int i = 0x11111111;
char szHexPrintBuf[10];
int ret_code = 0;
ret_code = sprintf(szHexPrintBuf, "%x", i);
if(0 > ret_code)
{
something-bad-happend();
}
Using the sprintf() function like this -- sprintf(charBuffer, "%x", i);
-- I think will work very well.

Resources