Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
main(){
char i[2];
* i = 0;
* (i + 1) = 1;
printf("len = %d \n",sizeof(int *));
printf("i[0] = %d \n",*(int *)i);
}
where the answer is not 16 the answer is 256
i use the turboc2.0 the hex is 100
This code depends on your system, specifically on the size of an int.
After initializing, your i array looks like this:
------------
|0x00 | 0x01 |
------------
Assumed an int is 32 bits on your system:
When casting i to an *int and dereferencing it, there will be four bytes which are accessed (since an int is 32 bits or four bytes):
--------------------------
|0x00 | 0x01 | 0x?? | 0x?? |
--------------------------
So, the last two bytes are out of bounds of your array, will have any value, and you will observe undefined behavior (on my system, actually, it prints different values each time I execute the code, like 1762656512, -375848704, ...).
Assumed an int is 16 bits on your system, it gets a littlebit "better":
In this case, when casting i to an *int and dereferencing it, the two bytes will be accessed as a 16 bit value. But, it then still depends on the endianess which value you get:
Little endian: *(int*) i = 0x0100 = 256
Big endian: *(int*) i = 0x0001 = 1
So, if you expect 256, you need to make sure to be on a little endian 16 bit system ...
BTW: When using sizeof() with printf(), make sure to use the %zu format specifier.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Given below code snippet :
#include <stdio.h>
#include<string.h>
union xyz
{
int j;
char b[2];
}y;
int main(void)
{
y.j=520;
printf("%d %d",y.b[0],y.b[1]);
y.b[0]=2;
printf(" %d ",y.j);
return 0;
}
For this code , I am not getting whether that whether the system is little endian or Big-endian , if y.j is 520 then we have the representation as :
0000001000000100 , so y.b[0] should be 2 and y.b[1] should be 4 ,but I am getting y.b[0] as 4 and y.b[1] as 2 ,and my machine is little-endian ,but I am not getting how is the architecture affecting the representation of y.b[0] and y.b[1] ?
In my opininon , whenever we create array there is nothing like Most significant byte of array and least significant byte of array , we have indexes like b[0] , b[1] , b[2] and so on , so then how is the architecture affecting the representation of array ?
Please explain .
To be on the safe side, let's use short int, which is more likely to be 16 bits.
union xyz {
short int j;
char b[2];
} y;
So after you say
y.j = 520;
then y.j looks like this:
+-------------+
y.j: | 520 |
+-------------+
On a big-endian machine y.b looks like this:
+------+------+
y.b: | 0x02 | 0x08 |
+------+------+
[0] [1]
On a little-endian machine y.b looks like this:
+------+------+
y.b: | 0x08 | 0x02 |
+------+------+
[0] [1]
Your machine is little endian. So the least significant byte is stored first. For your example that is 0x08. The upper byte will be 0x02.
y.b[0] access the first byte in memory. Not the first byte from left to right as the number is written on a page. So y.b[0] access 0x08, and y.b[1] accesses the second byte as stored in memory i.e. 0x02.
If your machine was big endian (and ints were 16 bit) then the first byte of the int stored in the memory would be 0x02, and the second byte would be 0x08. So y.b[0] would access 0x02, and y.b[1] accesses the second byte as stored in memory i.e. 0x08.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I want to learn if this is possible:
for ex:
we have long Lvalue = 0xFF00f41a;
and also have int *p;
Can we point to last 2 byte of Lvalue
like p=&Lvalue <<16;
p pointed frist 16 bit value is it possible?
*p --> f41a;
*(p+1) --->0xFF00;
then if
p = 0xa011;
long Lvalue ---> 0xFF00a011
actually I need bit operations. I have 32 bit value but I can send only 16 bits and if I change 16 bit have to change first 16 bit last 16 bit of 32 bit value.
If you just want 16bits of the larger 32bits type, use bit mask for the task, for example, to get the lower 16 bits of value:
long value = 0xFF00f41a;
long lower = value & 0xFFFF;
To change the lower 16 bits of value, use bit operation:
lower = <some thing new>;
value = (value & 0xFFFF0000) | lower;
Don't use pointer to access part of the 32bit value, it crates undefined bahavior when you dereference it.
Following short example will work, if int is aligned on 4-bytes (which seems to be guaranteed by gcc, see Casting an int pointer to a char ptr and vice versa):
#include <stdio.h>
int main() {
int v = 0xcafe;
int *ip = &v;
char *cp = (char*) ip;
printf("%hhX\n", *cp); // FE on little-endian box
printf("%hhX\n", *(cp + 1));
*cp = 0xbe;
*(cp + 1) = 0xba;
printf("%X\n", *ip);
return 0;
}
You can guarantee alignment of int thus:
int main() {
__attribute__ ((aligned (4))) int v = 0xcafe;
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Does anybody know how I can do a correct conversion from a uint16 to a uint8 in a C program for my STM32F091?
I thought that it was like this:
uint16_t Test = 0x565;
uint8_t Test2 = (uint8_t)Test;
But that doesn't work very well, so does anyone has a suggestion?
[update from comment:]
I use a potentiometer that has a minimum value of 0x0 and a maximum value of 0xFFF. Test must have the value of ADC1->DR (this is a value from the ADC in the STM32F0)
Edit:
You cannot compress the data without information lost in this case. Since your data range from ADC is 0x000 to 0xFFF - there is no way for you to represent the data perfectly without information/precision lost in uint8 byte whose range is only from 0x00 to 0xFF
But you still can map the data with precision lost. For example:
uint8_t Test2 = (unsigned)(Test >> 4);
Will cause you to map every 16 range to a single value:
0-15 -> 0
16-31 -> 1
32-47 -> 2
//and so on
Since you only have 8 LEDs anyway, you could use uint8 byte to control the LED - though you will lose precision of the real value, but you are still able to represent the range of the value (per unit of 16) correctly with your 8 LEDs (since you only have 8 LEDs anyway)
Original:
The case is very likely cause by overflow when you cast bigger-sized uint16 data type to smaller-sized uint8:
uint16_t Test = 0x565;
uint8_t Test2 = (uint8_t)Test; //Test2 value is only 0x65, 0x500 is missing
The casting causes the most significant byte value (0x500) to be truncated.
So Im using this (its from another question I did),
unsigned char *y = resultado->informacion;
int i = 0;
int tam = data->tamanho;
unsigned char resAfter;
for (int i=0; i<tam;i++)
{
unsigned char x = data->informacion[i];
x <<= 3;
if (i>0)
{
resAfter = (resAfter << 5) | x;
}
else
{
resAfter = x;
}
}
printf("resAfter es %s\n", resAfter);
so at the end I have this really long number (Im estimating about 43 bits), how can I get groups of 8 bits, I think im gettin something like (010101010101010.....000) and I want to separate this in groups of 8.
Another question, I know for sure that resAfter is going to have n number of bits where n is a multiply of 8 plus 3, so my question is: is this possible? or c is going to complete the byte? like if I get 43 bits then c is going to fill them with 0 and complete so I have 48 bits; and is there a way to delete these 3 bits?
Im new on c and bitwise so sorry if what Im doing is reallly bad.
Basically in programming you deal with bytes (i think, at least in most cases), in C you deal with types of specific size (depending on system you run it on).
That said char usually has size of 1 byte, and I don't really think you can playing around with single bits. I mean u can do operation on them (<< for instance) in scale of single bits but i don't know of any standard way to preserve less than 8 bits in variable in C (though i may be wrong about it)
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I was asked an interview question: given a 6 byte input, which got from a big endian machine, please implement a function to convert/typecast it to 8 bytes, assume we do not know the endian of the machine running this function.
The point of the question seems to test my understanding of endianess because I was asked whether I know endianess before this question.
I do not know how to answer the question. e.g. do I need to pad 6 byte to 8 byte first? and how? Here is my code. is it correct?
bool isBigEndian(){
int num = 1;
char* b = (char*)(&num);
return b ? false:true;
}
long long* convert(char* arr[]){ //size is 6
long long* res = (long long*)malloc(long long);//...check res is NULL...
if (isBigEnian()){
for(int i = 0; i< 6; i++)
memset(res, i+2, arr[i]);
}
else {
for(int i = 0; i< 6; i++)
memset(res, i+2, arr[6-1-i]);
}
return res; //assume caller will free res.
}
update: to answer that my question is not clear, I just found a link: Convert Bytes to Int / uint in C with the similar question. based on my understanding of that, endianess of the host does matters. suppose if input is: char array[] = {01,02,03,04,05,06}, then if host is little endian, output is stored as 00,00,06,05,04,03,02,01, if big endian, output will be stored as 00,00,01,02,03,04,05,06, in both case, the 0000 are padded at beginning.
I am a kind of understand now: in the other machine, suppose there is a number xyz = 010203040506 because it is bigendian and 01 is MSB. so it is stored as char array = {01,02,03,04,05,06} where 01 has lowest address. then in this machine, if the machine is also big endian. it should be stored as {00,00,01,02,03,04,05,06 } where 01 is still MSB, so that it is cast to the same number int_64 xyz2 = 0000010203040506. but if the machine is little endian, it should be stored as {00,00,06,05,04,03,02,01 } where 01 is MSB has highest address in order for int_32 xyz2 = 0000010203040506.
please let me know if my undestanding is incorrect. and Can anybody tell me why 0000 is always padded at beginning no matter what endianess? shouldn't it be padded at the end if this machine is little endian since 00 is Most sign byte?
Before moving on, you should have asked for clarification.
What exactly means converting here? Padding each char with 0's? Prefixing each char with 0's?
I will assume that each char should be prefixed with 0's. This is a possible solution:
#include <stdint.h>
#include <limits.h>
#define DATA_WIDTH 6
uint64_t convert(unsigned char data[]) {
uint64_t res;
int i;
res = 0;
for (i = 0; i < DATA_WIDTH; i++) {
res = (res << CHAR_BIT) | data[i];
}
return res;
}
To append 0's to each char, we could, instead, use this inside the for:
res = (res << CHAR_BIT) | (data[i] << 2);
In an interview, you should always note the limitations for your solution. This solution assumes that the implementation provides uint64_t type (it is not required by the C standard).
The fact that the input is big endian is important because it lets you know that data[0] corresponds to the most significant byte, and it must remain so in your result. This solution works not matter what the target machine's endianness.
I don't understand why you think malloc is necessary. Why not just something like this?
long long convert(unsigned char data[]);
{
long long res;
res = 0;
for( int i=0;i < 6; ++i)
res = (res << 8) + data[i];
return res;
}