C memcpy issues with unsigned char array - c

I have a question about memcpy that I hope someone can answer. Here's a short demonstrative program:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main (int argc, char **argv){
unsigned char buffer[10];
unsigned short checksum = 0x1234;
int i;
memset(buffer, 0x00, 10);
memcpy(buffer, (const unsigned char*)&checksum, 2);
for(i = 0; i < 10; i ++){
printf("%02x",buffer[i]);
}
printf("\n");
return 0;
}
When I run this program, I get 34120000000000000000.
My question is why don't I get 12340000000000000000?
Thanks so much

You are getting 34120000000000000000 because you are on a little-endian system. You would get 12340000000000000000 on a big-endian system. Endianness gives a full discussion of big-endian vs. little-endian systems.

little endian/big endian architecture ?
which mean that 2 byte of checksum is inverted.
It is just a guess, if my answer is not true Comment it and I will delete it.

Intel's CPUs are little endian, they store numbers little word first
This is apparently evidence that Intel don't do inhouse drug testing.

Related

How can I copy 4 letter ascii word to buffer in C?

I am trying to copy the word: 0x0FF0 to a buffer but unable to do so.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <time.h>
#include <linux/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
void print_bits(unsigned int x);
int main(int argc, char *argv[])
{
char buffer[512];
unsigned int init = 0x0FF0;
unsigned int * som = &init;
printf("print bits of som now: \n");
print_bits(init);
printf("\n");
memset(&buffer[0], 0, sizeof(buffer)); // reinitialize the buffer
memcpy(buffer, som, 4); // copy word to the buffer
printf("print bits of buffer[0] now: \n");
print_bits(buffer[0]);
printf("\n");
return 0;
}
void print_bits(unsigned int x)
{
int i;
for (i = 8 * sizeof(x)-17; i >= 0; i--) {
(x & (1 << i)) ? putchar('1') : putchar('0');
}
printf("\n");
}
this is the result I get in the console:
Why am I getting different values from the bit printing if I am using memcpy?
Don't know if it has something to do with big-little-endian but I am losing 4 bits of 1's here so in both of the methods it shouldn't happen.
When you call
print_bits(buffer[0]);
you're taking just one byte out of the buffer, converting it to unsigned int, and passing that to the function. The other bytes in buffer are ignored.
You are mixing up types and relying on specific settings of your architecture/platform; This already breaks your existing code, and it may get even more harmful once you compile with different settings.
Your buffer is of type char[512], while your init is of type unsigned int.
First, it depends on the settings whether char is signed or unsigned char. This is actually relevant, since it influences how a char-value is promoted to an unsigned int-value. See the following code that demonstrated the difference using explicitly signed and unsigned chars:
signed char c = 0xF0;
unsigned char uc = c;
unsigned int ui_from_c = c;
unsigned int ui_from_uc = uc;
printf("Singned char c:%hhd; Unsigned char uc:%hhu; ui_from_c:%u ui_from_uc:%u\n", c, uc, ui_from_c,ui_from_uc);
// output: Singned char c:-16; Unsigned char uc:240; ui_from_c:4294967280 ui_from_uc:240
Second, int may be represented by 4 or by 8 bytes (which can hold a "word"), yet char will typically be 1 byte and can therefore not hold a "word" of 16 bit.
Third, architectures can be big endian or little endian, and this influences where a constant like 0x0FF0, which requires 2 bytes, would actually be located in a 4 or 8 byte integral representation.
So it is for sure that buffer[0] selects just a portion of that what you think it does, the portion might get promoted in the wrong way to an unsigned int, and it might even be a portion completely out of the 0x0FF0-literal.
I'd suggest to use fixed-width integral values representing exactly a word throughout:
#include <stdio.h>
#include <stdint.h>
void print_bits(uint16_t x);
int main(int argc, char *argv[])
{
uint16_t buffer[512];
uint16_t init = 0x0FF0;
uint16_t * som = &init;
printf("print bits of som now: \n");
print_bits(init);
printf("\n");
memset(buffer, 0, sizeof(buffer)); // reinitialize the buffer
memcpy(buffer, som, sizeof(*som)); // copy word to the buffer
printf("print bits of buffer[0] now: \n");
print_bits(buffer[0]);
printf("\n");
return 0;
}
void print_bits(uint16_t x)
{
int i;
for (i = 8 * sizeof(x); i >= 0; i--) {
(x & (1 << i)) ? putchar('1') : putchar('0');
}
printf("\n");
}
You are not writing the bytes "0F F0" to the buffer. You are writing whatever bytes your platform uses internally to store the number 0x0FF0. There is no reason these need to be the same.
When you write 0x0FF0 in C, that means, roughly, "whatever my implementation uses to encode the number four thousand eighty". That might be the byte string 0F, F0. But it might not be.
I mean, how weird would it be if unsigned int init = 0x0FF0; and unsigned int init = 4080; would do the same thing on some platforms and different things on others? But surely not all platforms store the number 4,080 using the byte string "0F F0".
For example, I might store the number ten as "10" or "ten" or any number of other ways. It's unreasonable for you to expect "ten", "10", or any other particular byte sequence to appear in memory just because you stored the number ten unless you do happen to specifically know how your platform stores the number ten. Given that you asked this question, you don't know that.
Also, you are only printing the value of buffer[0], which is a single character. So it couldn't possibly hold any version of 0x0FF0.

How to get the bit position of any member in structure

How can I get the bit position of any members in structure?
In example>
typedef struct BitExamStruct_
{
unsigned int v1: 3;
unsigned int v2: 4;
unsigned int v3: 5;
unsigned int v4: 6;
} BitExamStruct;
Is there any macro to get the bit position of any members like GetBitPos(v2, BitExamStruct)?
I thought that compiler might know members' location based on bits length in the structure. So I want to know whether I can get it by using just a simple macro without running code.
Thank you in advance.
There is no standard way that I know of to do so, but it doesn't mean you can't find a solution.
The following is not the prettiest code ever; it's a kind of hack to identify where the variable "begins" in memory. Please keep in mind that the following can give different results depending on the endianess:
#include <stdio.h>
#include <string.h>
typedef struct s_toto
{
int a:2;
int b:3;
int c:3;
} t_toto;
int
main()
{
t_toto toto;
unsigned char *c;
int bytes;
int bits;
memset(&toto, 0, sizeof(t_toto));
toto.c = 1;
c = (unsigned char *)&toto;
for (bytes = 0; bytes < (int)sizeof(t_toto); bytes++)
{
if (*c)
break;
}
for (bits = 0; bits < 8; bits++)
{
if (*c & 0b10000000)
break;
*c = (*c << 1);
}
printf("position (bytes=%d, bits=%d): %d\n", bytes, bits, (bytes * 8) + bits);
return 0;
}
What I do is that I initialize the whole structure to 0 and I set 1 as value of the variable I want to locate. The result is that only one bit is set to 1 in the structure. Then I read the memory byte per byte until I find one that's not zero. Once found, I can look at its bits until I find the one that's set.
There is no portable (aka standard C) way. But thinking outside the box, if you need full control or need this information badly, bitfields are the wrong approach. The proper solution is shifting and masking. Of course this is feasible only when you are in control of the source code.

2 Chars to Short in C

I've got 2 chars.
Char 128 and Char 2.
How do I turn these chars into the Short 640 in C?
I've tried
unsigned short getShort(unsigned char* array, int offset)
{
short returnVal;
char* a = slice(array, offset, offset+2);
memcpy(&returnVal, a, 2);
free(a);
return returnVal;
}
But that didn't work, it just displays it as 128. What's the preferred method?
Probably the easiest way to turn two chars, a and b, into a short c, is as follows:
short c = (((short)a) << 8) | b;
To fit this into what you have, the easiest way is probably something like this:
unsigned short getShort(unsigned char* array, int offset)
{
return (short)(((short)array[offset]) << 8) | array[offset + 1];
}
I found that the accepted answer was nearly correct, except i'd run into a bug where sometimes the top byte of the result would be 0xff...
I realized this was because of C sign extension. if the second char is >= 0x80, then converting 0x80 to a short becomes 0xff80. Performing an 'or' of 0xff80 with anything results in the top byte remaining 0xff.
The following solution avoids the issue by zeroing out the top byte of b during its implicit conversion to a short.
short c = (((short)a) << 8) | (0x00ff & b);
I see that there is already an answer, but I'm a bit puzzled about what was going on with your original attempt. The following code shows your way and a technique using a union. Both seem to work just fine. I suppose you might have been running into an endianness problem. Anyway, perhaps this demonstration will be useful even if your problem is already solved.
#include <stdio.h>
#include <string.h>
int main()
{
short returnVal;
char a[2];
union {
char ch[2];
short n;
} char2short;
a[0] = 128;
a[1] = 2;
memcpy(&returnVal, a, 2);
printf("short = %d\n", returnVal);
char2short.ch[0] = 128;
char2short.ch[1] = 2;
printf("short (union) = %d\n", char2short.n);
return 0;
}
Outputs:
short = 640
short (union) = 640
I see that you are not actually trying to shift bits but assemble the equivelant of hex values together, like you would color values in CSS.
Give this code a shot:
char b1=128,b2=2;
char data[16];
sprintf((char *)data,"%x%x",(BYTE)b2,(BYTE)b1);
short result=strtol(data,(char **)NULL, 16);

Test big endian [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Little vs Big Endianess: How to interpret the test
Is there an easy method to test code with gcc or any online compiler like ideone for big endian? I don't want to use qemu or virtual machines
EDIT
Can someone explain the behavior of this piece of code on a system using big endian?
#include <stdio.h>
#include <string.h>
#include <stdint.h>
int main (void)
{
int32_t i;
unsigned char u[4] = {'a', 'b', 'c', 'd'};
memcpy(&i, u, sizeof(u));
printf("%d\n", i);
memcpy(u, &i, sizeof(i));
for (i = 0; i < 4; i++) {
printf("%c", u[i]);
}
printf("\n");
return 0;
}
As a program?
#include <stdio.h>
#include <stdint.h>
int main(int argc, char** argv) {
union {
uint32_t word;
uint8_t bytes[4];
} test_struct;
test_struct.word = 0x1;
if (test_struct.bytes[0] != 0)
printf("little-endian\n");
else
printf("big-endian\n");
return 0;
}
On a little-endian architecture, the least significant byte is stored first. On a big-endian architecture, the most-significant byte is stored first. So by overlaying a uint32_t with a uint8_t[4], I can check to see which byte comes first. See: http://en.wikipedia.org/wiki/Big_endian
GCC in particular defines the __BYTE_ORDER__ macro as an extension. You can test against __ORDER_BIG_ENDIAN__, __ORDER_LITTLE_ENDIAN__, and __ORDER_PDP_ENDIAN__ (which I didn't know existed!) -- see http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
See also http://en.wikipedia.org/wiki/Big_endian
As for running code in an endianness that doesn't match your machine's native endianness, then you're going to have to compile and run it on an architecture that has that different endianness. So you are going to need to cross-compile, and run on an emulator or virtual machine.
edit: ah, I didn't see the first printf().
The first printf will print "1633837924", since a big-endian machine will interpret the 'a' character as the most significant byte in the int.
The second printf will just print "abcd", since the value of u has been copied byte-by-byte back and forth from i.

C program to check little vs. big endian [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C Macro definition to determine big endian or little endian machine?
int main()
{
int x = 1;
char *y = (char*)&x;
printf("%c\n",*y+48);
}
If it's little endian it will print 1. If it's big endian it will print 0. Is that correct? Or will setting a char* to int x always point to the least significant bit, regardless of endianness?
In short, yes.
Suppose we are on a 32-bit machine.
If it is little endian, the x in the memory will be something like:
higher memory
----->
+----+----+----+----+
|0x01|0x00|0x00|0x00|
+----+----+----+----+
A
|
&x
so (char*)(&x) == 1, and *y+48 == '1'. (48 is the ascii code of '0')
If it is big endian, it will be:
+----+----+----+----+
|0x00|0x00|0x00|0x01|
+----+----+----+----+
A
|
&x
so this one will be '0'.
The following will do.
unsigned int x = 1;
printf ("%d", (int) (((char *)&x)[0]));
And setting &x to char * will enable you to access the individual bytes of the integer, and the ordering of bytes will depend on the endianness of the system.
This is big endian test from a configure script:
#include <inttypes.h>
int main(int argc, char ** argv){
volatile uint32_t i=0x01234567;
// return 0 for big endian, 1 for little endian.
return (*((uint8_t*)(&i))) == 0x67;
}
Thought I knew I had read about that in the standard; but can't find it. Keeps looking. Old; answering heading; not Q-tex ;P:
The following program would determine that:
#include <stdio.h>
#include <stdint.h>
int is_big_endian(void)
{
union {
uint32_t i;
char c[4];
} e = { 0x01000000 };
return e.c[0];
}
int main(void)
{
printf("System is %s-endian.\n",
is_big_endian() ? "big" : "little");
return 0;
}
You also have this approach; from Quake II:
byte swaptest[2] = {1,0};
if ( *(short *)swaptest == 1) {
bigendien = false;
And !is_big_endian() is not 100% to be little as it can be mixed/middle.
Believe this can be checked using same approach only change value from 0x01000000 to i.e. 0x01020304 giving:
switch(e.c[0]) {
case 0x01: BIG
case 0x02: MIX
default: LITTLE
But not entirely sure about that one ...

Resources