Formatting SprintF in C - c

The question i have with the code below, is where i have used sprintf, i want it to insert a formatted int, because the client then picks up the data and pulls out data according to char array. So the client will pick up from the received code the delay from [0] and [1]. Where as another variable may be taken from the [2] and [3] that is sent from another bit of code. What is the way to format it like in printf to be saved in a char[]
int sock = *(int*)data->sock;
int i,startDelay =0;
char buffer[SEND_MESSAGE_LENGTH];
puts("Run Machine Called");
for(startDelay=11;startDelay>=0;startDelay--)
{
printf("Start Delay:%i\n",startDelay);
sprintf(buffer,"%2i",startDelay);
printf("Send Data - %2i - Start Delay\n",*buffer-'0');
//write_sock(sock,buffer);
sleep(1);
}

I'm not certain, but I think you're talking about a 2-byte (16-bit) integer value. If so, then sprintf is not the right tool for the job. Instead, you should take the integer and mask and shift to extract the 16 bits:
buffer[0] = startDelay & 0xFF; // low byte
buffer[1] = (startDelay >> 8) & 0xFF; // high byte
Of course, since your values are smaller than 255, the high byte here will always be zero, so it simplifies to:
buffer[0] = startDelay & 0xFF;
buffer[1] = 0;
It's not clear to me what the byte order should be, so you may have to reverse these and put the high byte in buffer[0] and the low byte in buffer[1].

Related

Is reading one byte at a time endianness agnostic regardless of value size?

Say I am reading and writing uint32_t values to and from a stream. If I read/write one byte at a time to/from a stream and shift each byte like the below examples, will the results be consistent regardless of machine endianness?
In the examples here the stream is a buffer in memory called p.
static uint32_t s_read_uint32(uint8_t** p)
{
uint32_t value;
value = (*p)[0];
value |= (((uint32_t)((*p)[1])) << 8);
value |= (((uint32_t)((*p)[2])) << 16);
value |= (((uint32_t)((*p)[3])) << 24);
*p += 4;
return value;
}
static void s_write_uint32(uint8_t** p, uint32_t value)
{
(*p)[0] = value & 0xFF;
(*p)[1] = (value >> 8 ) & 0xFF;
(*p)[2] = (value >> 16) & 0xFF;
(*p)[3] = value >> 24;
*p += 4;
}
I don't currently have access to a big-endian machine to test this out, but the idea is if each byte is written one at a time each individual byte can be independently written or read from the stream. Then the CPU can handle endianness by hiding these details behind the shifting operations. Is this true, and if not could anyone please explain why not?
If I read/write one byte at a time to/from a stream and shift each byte like the below examples, will the results be consistent regardless of machine endianness?
Yes. Your s_write_uint32() function stores the bytes of the input value in order from least significant to most significant, regardless of their order in the native representation of that value. Your s_read_uint32() correctly reverses this process, regardless of the underlying representation of uint32_t. These work because
the behavior of the shift operators (<<, >>) is defined in terms of the value of the left operand, not its representation
the & 0xff masks off all bits of the left operand but those of its least-significant byte, regardless of the value's representation (because 0xff has a matching representation), and
the |= operations just put the bytes into the result; the positions are selected, appropriately, by the preceding left shift. This might be more clear if += were used instead, but the result would be no different.
Note, however, that to some extent, you are reinventing the wheel. POSIX defines a function pair htonl() and nothl() -- supported also on many non-POSIX systems -- for dealing with byte-order issues in four-byte numbers. The idea is that when sending, everyone uses htonl() to convert from host byte order (whatever that is) to network byte order (big endian) and sends the resulting four-byte buffer. On receipt, everyone accepts four bytes into one number, then uses ntohl() to convert from network to host byte order.
It'll work but a memcpy followed by a conditional byteswap will give you much better codegen for the write function.
#include <stdint.h>
#include <string.h>
#define LE (((char*)&(uint_least32_t){1})[0]) // little endian ?
void byteswap(char*,size_t);
uint32_t s2_read_uint32(uint8_t** p)
{
uint32_t value;
memcpy(&value,*p,sizeof(value));
if(!LE) byteswap(&value,4);
return *p+=4, value;
}
void s2_write_uint32(uint8_t** p, uint32_t value)
{
memcpy(*p,&value,sizeof(value));
if(!LE) byteswap(*p,4);
*p+=4;
}
Gcc since the 8th series (but not clang) can eliminate this shifts on a little-endian platforms, but you should help it by restrict-qualifying the doubly-indirect pointer to the destination, or else it might think that a write to (*p)[0] can invalidate *p (uint8_t is a char type and therefore permitted to alias anything).
void s_write_uint32(uint8_t** restrict p, uint32_t value)
{
(*p)[0] = value & 0xFF;
(*p)[1] = (value >> 8 ) & 0xFF;
(*p)[2] = (value >> 16) & 0xFF;
(*p)[3] = value >> 24;
*p += 4;
}

Is there a simpler way to take a substring of an char array and convert it to a long in C?

I am looking for a shorter/more elegant way to get an NTP timestamp from a received NTP packet. The packet is stored in an unsigned char array, buf, from the socket function recvfrom:
unsigned char buf[48];
recvfrom(sockfd, buf, 48, 0, (struct sockaddr *) &their_addr, &addr_len));
I am then copying the value of the 40th-43rd elements which represent a 32-bit timestamp of seconds into an unsigned long, transSec, with bitshifting like so:
recvPacket->transmitSec = buf[40];
recvPacket->transSec <<= 8;
recvPacket->transSec |= buf[41];
recvPacket->transSec <<= 8;
recvPacket->transSec |= buf[42];
recvPacket->transSec <<= 8;
recvPacket->transSec |= buf[43];
This works fine, but in the interest of learning, is there a shorter/more elegant way of doing this? I have tried memcpy:
memcpy(&recvPacket->transSec, &buf[40], sizeof(unsigned long));
And some other variations of the above, but am getting incorrect numbers. I am not particularly confident I'm using it correctly.
What this might be actually is an endianness issue. Check the wiki entry here: http://en.wikipedia.org/wiki/Endianness. In short, the byte ordering of a type isn't necessarily the same from one system to another. It looks like you're doing network communication - check out the byte order conversion family functions:
http://beej.us/guide/bgnet/output/html/multipage/htonsman.html
Note that buf[40] is the first byte from the stream, and is being shifted all the way to the highest byte of the underlying type. memcpy on the other hand, will copy buf[40] into the 0-offset of transSec - effectively the byte order is reversed in your two examples.
You can check it out in your code like this, you'll declare a character pointer ( character being the smallest addressable type in c) and walk the length of the size of the type from the address you're inspecting, to the address+sizeof(type):
// declare a char *
char * walker;
// set it to your integer
walker = (char *)&(recvPacket->transSec);
for ( i = 0; i < sizeof(unsigned long); i++){
// print out the bytes from memory address[0] - address[3] ( assuming 4-byte unsigned long)
printf("%x\n", walker[i]);
}
You can walk buff like this too, but that's already a char buffer so, you might as well just print it. I think you'll see the byte order reversed.

fetch 32bit instruction from binary file in C

I need to read 32bit instructions from a binary file.
so what i have right now is:
unsigned char buffer[4];
fread(buffer,sizeof(buffer),1,file);
which will put 4 bytes in an array
how should I approach that to connect those 4 bytes together in order to process 32bit instruction later?
Or should I even start in a different way and not use fread?
my weird method right now is to create an array of ints of size 32 and the fill it with bits from buffer array
The answer depends on how the 32-bit integer is stored in the binary file. (I'll assume that the integer is unsigned, because it really is an id, and use the type uint32_t from <stdint.h>.)
Native byte order The data was written out as integer on this machine. Just read the integer with fread:
uint32_t op;
fread(&op, sizeof(op), 1, file);
Rationale: fread read the raw representation of the integer into memory. The matching fwrite does the reverse: It writes the raw representation to thze file. If you don't need to exchange the file between platforms, this is a good method to store and read data.
Little-endian byte order The data is stored as four bytes, least significant byte first:
uint32_t op = 0u;
op |= getc(file); // 0x000000AA
op |= getc(file) << 8; // 0x0000BBaa
op |= getc(file) << 16; // 0x00CCbbaa
op |= getc(file) << 24; // 0xDDccbbaa
Rationale: getc reads a char and returns an integer between 0 and 255. (The case where the stream runs out and getc returns the negative value EOF is not considered here for brevity, viz laziness.) Build your integer by shifting each byte you read by multiples of 8 and or them with the existing value. The comments sketch how it works. The capital letters are being read, the lower-case letters were already there. Zeros have not yet been assigned.
Big-endian byte order The data is stored as four bytes, least significant byte last:
uint32_t op = 0u;
op |= getc(file) << 24; // 0xAA000000
op |= getc(file) << 16; // 0xaaBB0000
op |= getc(file) << 8; // 0xaabbCC00
op |= getc(file); // 0xaabbccDD
Rationale: Pretty much the same as above, only that you shift the bytes in another order.
You can imagine little-endian and big-endian as writing the number one hundred and twenty tree (CXXIII) as either 321 or 123. The bit-shifting is similar to shifting decimal digtis when dividing by or multiplying with powers of 10, only that you shift my 8 bits to multiply with 2^8 = 256 here.
Add
unsigned int instruction;
memcpy(&instruction,buffer,4);
to your code. This will copy the 4 bytes of buffer to a single 32-bit variable. Hence you will get connected 4 bytes :)
If you know that the int in the file is the same endian as the machine the program's running on, then you can read straight into the int. No need for a char buffer.
unsigned int instruction;
fread(&instruction,sizeof(instruction),1,file);
If you know the endianness of the int in the file, but not the machine the program's running on, then you'll need to add and shift the bytes together.
unsigned char buffer[4];
unsigned int instruction;
fread(buffer,sizeof(buffer),1,file);
//big-endian
instruction = (buffer[0]<<24) + (buffer[1]<<16) + (buffer[2]<<8) + buffer[3];
//little-endian
instruction = (buffer[3]<<24) + (buffer[2]<<16) + (buffer[1]<<8) + buffer[0];
Another way to think of this is that it's a positional number system in base-256. So just like you combine digits in a base-10.
257
= 2*100 + 5*10 + 7
= 2*10^2 + 5*10^1 + 7*10^0
So you can also combine them using Horner's rule.
//big-endian
instruction = ((((buffer[0]*256) + buffer[1]*256) + buffer[2]*256) + buffer[3]);
//little-endian
instruction = ((((buffer[3]*256) + buffer[2]*256) + buffer[1]*256) + buffer[0]);
#luser droog
There are two bugs in your code.
The size of the variable "instruction" must not be 4 bytes: for example, Turbo C assumes sizeof(int) to be 2. Obviously, your program fails in this case. But, what is much more important and not so obvious: your program will also fail in case sizeof(int) be more than 4 bytes! To understand this, consider the following example:
int main()
{ const unsigned char a[4] = {0x21,0x43,0x65,0x87};
const unsigned char* p = &a;
unsigned long x = (((((p[3] << 8) + p[2]) << 8) + p[1]) << 8) + p[0];
printf("%08lX\n", x);
return 0;
}
This program prints "FFFFFFFF87654321" under amd64, because an unsigned char variable becomes SIGNED INT when it is used! So, changing the type of the variable "instruction" from "int" to "long" does not solve the problem.
The only way is to write something like:
unsigned long instruction;
instruction = 0;
for (int i = 0, unsigned char* p = buffer + 3; i < 4; i++, p--) {
instruction <<= 8;
instruction += *p;
}

Transfering an int as two bytes on the Arduino

I'm sampling at high frequencies and need to transmit the 10-bit ADC value via UART out of my Arduino.
By default, it uses a byte per character. So if doing an analogRead would yield the value of "612", it would send via UART "6" as one byte, "1" as one byte, "2" as one byte, and the line terminator as the last byte.
Given that my sampling rate is truncated by this communication, it's important that it's as efficient and uniform as possible, so I'm trying to force it to use two bytes to transmit that data, doesn't matter what the data actual is (by default it would use three bytes to transmit "23", four bytes to transmit "883" and five bytes to transmit "1001").
Currently, I'm doing something like this, which is the best way I've found:
int a = 600; //Just an example
char high = (char)highByte(a);
char low = (char)lowByte(a);
Serial.print(high);
Serial.println(low);
Currently this uses three bytes (including \n) regardless of the value. Is there an even more efficient method?
Just printing it with something like
Serial.print(foo, BIN);
Doesn't work at all. It actually uses one byte per every single bit of the binary representation of foo, which is quite silly.
I might be missing something, but why don't you use Serial.write(byte)?
You can use a methode like this one:
void writeIntAsBinary(int value){
Serial.write(lowByte(value));
Serial.write(highByte(value));
}
what are you planning to do with the data on your computer?
If you're sending binary data over a serial line, you really shouldn't confuse everything by using a text-style linefeed separator.
On the other hand, it's kind of hard (for the other end) to know which byte is which, without some kind of synchronization help.
But, since you only have 10 bits of payload, but send 16 bits of data, you can "do a UTF-8" and use a free bit to signal "start of value". This will require using only 7 bits of each 8-bit byte for your payload, but that's fine since 7 + 7 = 14 which is way more than 10. We can let the 8th bit mean "this is the high byte of a new pair of bytes":
const int a = 600;
const unsigned char high = ((a >> 7) & 0x7f) | 0x80;
const unsigned char low = (a & 0x7f);
Serial.print(high);
Serial.print(low);
In the above, the two bytes transmitted will be:
high == ((600 >> 7) & 0x7f) | 0x80 == 4 | 0x80 == 0x84
low == (600 & 0x7f) == 88 == 0x58
The receiver will have to do the above in reverse:
const int value = ((high & 0x7f) << 7) | low;
This should work, and uses the most-significant bit of the high byte, which is sent first, to signify that that is indeed the high byte. The low byte will never have the MSB set.

Easy way to convert a string of 0's and 1's into a character? Plain C

I'm doing a steganography project where I read in bytes from a ppm file and add the least significant bit to an array. So once 8 bytes are read in, I would have 8 bits in my array, which should equal some character in a hidden message. Is there an easy way to convert an array of 0's and 1's into an ascii value? For example, the array: char bits[] = {0,1,1,1,0,1,0,0} would equal 't'. Plain C
Thanks for all the answers. I'm gonna give some of these a shot.
A simple for loop would work - something like
unsigned char ascii = 0;
unsigned char i;
for(i = 0; i < 8; i++)
ascii |= (bits[7 - i] << i);
There might be a faster way to do this, but this is a start at least.
I wouldn't store the bits in an array -- I'd OR them with a char.
So you start off with a char value of 0: char bit = 0;
When you get the first bit, OR it with what you have: bit |= bit_just_read;
Keep doing that with each bit, shifting appropriately; i.e., after you get the next bit, do bit |= (next_bit << 1);. And so forth.
After you read your 8 bits, bit will be the appropriate ASCII value, and you can print it out or do whatever with it you want to do.
I agree with mipadi, don't bother storing in an array first, that's kind of pointless. Since you have to loop or otherwise keep track of the array index while reading it in, you might as well do it in one go. Something like this, perhaps?
bits = 0;
for ( i = 0; i < 8; ++i ) {
lsb = get_byte_from_ppm_somehow() & 0x01;
bits <<= 1 | lsb;
}
As long as the bit endian is correct, this should work and compile down pretty small.
If the bit endian is backwards then you should be able to change the initial value of mask to 1, the mask shift to <<= , and you might need to have (0x0ff & mask) as the do{}while conditional if your compiler doesn't do what it's supposed to with byte sized variables.
Don't forget to do something for the magic functions that I included where I didn't know what you wanted or how you did something
#include <stdint.h> // needed for uint8_t
...
uint8_t acc, lsb, mask;
uint8_t buf[SOME_SIZE];
size_t len = 0;
while (is_there_more_ppm_data()) {
acc = 0;
mask = 0x80; // This is the high bit
do {
if (!is_there_more() ) {
// I don't know what you think should happen if you run out on a non-byte boundary
EARLY_END_OF_DATA();
break;
}
lsb = 1 & get_next_ppm_byte();
acc |= lsb ? mask : 0; // You could use an if statement
mask >>= 1;
} while (mask);
buf[len] = acc; // NOTE: I didn't worry about the running off the end of the buff, but you should.
len++;
}

Resources