Storing int value into char p[] index - c

Been stuck on a problem. figured out my issue. I have looked online quite a bit and have read many possible solutions, but nothing seems to work for me.
I have this program, lets call it test.c
#include <stdio.h>
int main() {
int x = 21345;
char p[10];
p[0] = x;
printf("%d\n", x);
printf("%d", p[0]);
return 0;
}
As you would guess, I want the two printf statements to have the same output. Instead, I get the following output...
21345
97
I need 21345 to be at p[0], and when I call printf("%d", p[0]);
It needs to print out 21345, not 97
Any help? :(
EDIT:
Looks like you guys answered, thanks! Changing to int p[10] would solve the problem. I have another complication though, I also need to be able to store strings inside the indexes of p, along with ints.. how should I tackle this?

A char does not have the same type as int and is not identical in number of bits. You would need int p[10]; for that to work.

You have an array of signed chars, they take 1 byte each, the max value would be 127 and minimum -128. Now the x's value takes more bytes to represent, there is an overflow, and it truncates the leftmost bits,
21345 has the binary representation: 0101 0011 0110 0001
now discard the leftmost byte and you get: 0110 0001 which is 97

char store only 1 byte value so that you are getting that output. If you change char p[10] to int p[10] you will get output.

char is simply not big enough to store 21345. Therefore compiler takes just low 8 bits and puts them into char, so it becomes 97. When passing to printf it will convert it back to int but the highest bits are already lost.

You need to use int array instead of char
It should be like
#include <stdio.h>
int main() {
int x = 21345;
int p[10];
p[0] = x;
printf("%d\n", x);
printf("%d", p[0]);
return 0;
}
Output
21345
21345
Well if you want to use same array for strings too, use 2 dimensions char array
because you can store a integer value in 4 characters array correctly.
so you need to use p[10][4]
Now store each byte of int in corresponding char array index
p[0][0] = (x >> (8*0)) & 0xff;
p[0][1] = (x >> (8*1)) & 0xff;
p[0][2] = (x >> (8*2)) & 0xff;
p[0][3] = (x >> (8*3)) & 0xff;

Related

C - fail to convert unsigned char array to double

I would like to convert a unsigned char array to double in C. I tried many way to do so but still wrongly converted to 0.00000.
union {
double longtitude;
unsigned char bytes[sizeof(double)];
}u;
unsigned char * receive_buffer = malloc(65536);
int recv = recv(fd,receive_buffer,65536,0);
// the buffer should has 8 byte value {40 5c 80 23 8d a3 c2 12}
memcpy(&u.bytes,receive_buffer,sizeof(double)); // copy to char array
for ( int i=8;i>=0;i--){
u.longtitude = u.bytes[i];
}
printf("%lf",u.longtitude); // the result is 0.000000 / the expected result should be 114.00217
I got the result of '0.000000' from above code that I found from internet. How can I convert the char array to double? What's wrong in above code?
UPDATE
I added more specific code above. I have checked the contents of the receive_buffer and it contains the value in the above comment. The u.bytes correctly gets a value from the buffer via memcpy. The union and for loop part is the way I found from other similar questions. I tried it, but got result = 0.000000. Sorry about the unclear code posted and problem stated before; I am quite new to C language.
Delete the for loop.
The memcpy copies the bytes from the buffer into the bytes array of the union. Those are the same bytes used for the longitude member, so they are already in place. You do not need the for loop to copy those bytes, and it was incorrectly writing the values of the bytes into the value of the double rather than into the bytes that represent the value. Also, the loop index was wrong, as it was using 8 in the first iteration, but the bytes in an eight-byte object are indexed 0 to 7.
More than that, in C, you can modify the bytes that repesent an object with either a union or a memcpy. You do not need both. After the recv, this suffices:
double longitude;
memcpy(&longitude, receive_buffer, sizeof longitude);
I expect you could even do the recv directly into &longitude.
Remove the for loop entirely. I'm not sure what your intent in having it there is, but it undoes (or rather just clobbers) the work you just did.
Based on your update and the expected value of 114.00217, the issue is endian-ness. Whatever machine you are getting the value from does not have the same endianess as your machine. So after converting to double, swap endianess.
// endian_swap() function taken from https://stackoverflow.com/a/21507710/669576
// I modified to work with double
double endian_swap(double d)
{
long x = *(long *)&d;
x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8;
return *(double *)&x;
}
int main(void) {
unsigned char s[] = {0x40,0x5c,0x80,0x23,0x8d,0xa3,0xc2,0x12};
double d;
// Just copy - no union needed
memcpy(&d, s, sizeof(d));
// Swap endianess
d = endian_swap(d);
printf("%lf\n", d);
return 0;
}
Output: 114.002170
I don't do a lot of network programming, but I believe the ntohl() function is used for this. However, I don't know if there is a 64-bit version.
Update: Also, you can use htobe64() (Thanks to #Stargateur):
#include <endian.h>
int main(void) {
unsigned char s[] = {0x40,0x5c,0x80,0x23,0x8d,0xa3,0xc2,0x12};
// htobe64() expects a long, so use that first
long l;
memcpy(&l, s, sizeof(l));
l = htobe64(l);
// Then copy the swapped long bits to a double
double d;
memcpy(&d, &l, sizeof(d));
printf("%lf\n", d);
return 0;
}

Confusion on printing strings as integers in C

I would like to know how the string is represented in integer, so I wrote the following program.
#include <stdio.h>
int main(int argc, char *argv[]){
char name[4] = {"#"};
printf("integer name %d\n", *(int*)name);
return 0;
}
The output is:
integer name 64
This is understandable because # is 64 in integer, i.e., 0x40 in hex.
Now I change the program into:
#include <stdio.h>
int main(int argc, char *argv[]){
char name[4] = {"##"};
printf("integer name %d\n", *(int*)name);
return 0;
}
The output is:
integer name 16448
I dont understand this. Since ## is 0x4040 in hex. So it should be 2^12+2^6 = 4160
If I count the '\0' at the end of the string, then it should be 2^16+2^10 = 66560
Could someone explain where 16448 comes from?
Your math is wrong: 0x4040 == 16448. The two fours are the 6th and 14th bits respectively.
Your code actually invokes undefined behavior because you must not alias a char * with an int *. This is known as the strict aliasing rule. To see just one reason why this should be disallowed, consider what would otherwise have to happen if the code is run on a little and a big endian machine.
If you want to see the hex pattern of the string, you should simply loop over its bytes and print out each byte.
void
print_string(const char * strp)
{
printf("0x");
do
printf("%02X", (unsigned char) *strp);
while (*strp++);
printf("\n");
}
Of course, instead of printing the bytes, you can shift them into an integer (that will very soon overflow) and only finally output that integer. While doing this, you'll be forced to take a stand on “your” endianness.
/* Interpreting as big endian. */
unsigned long
int_string(const char * strp)
{
unsigned long value = 0UL;
do
value = (value << 8) | (unsigned char) *strp;
while (*strp++);
return value;
}
This is how 16448 comes :
0x4040 can be written like this in binary :
4 0 4 0 -> Hex
0100 0000 0100 0000 -> Binary
2^14 2^6 = 16448
Because here 6th and 14th bit are set.
Hope you got it :)

Assigning address of an int to a char pointer

In the following program, suppose a is stored at address 1000 and an int takes up 4bytes of storage. Now, c will point to the base address ie, 1000 and incrementing it by 3 will make it point to address 1003. Now, printing the character pointed to by c must give me the character corresponding to ascii 65. But it prints nothing!
#include<stdio.h>
#include<stdlib.h>
int main(){
int a = 65;
char *c = &a;
printf("%c\n", *(c+3));
}
What is wrong in my reasoning?
You didn't take endianness into account. On a little-endian system, the 'a' (or if the encoding isn't ASCII compatible, whatever 65 is) will be in the first byte, and the other bytes are 0. Passing a 0 byte to printf("%c\n",_); prints out nothing but the newline.
printing the character pointed to by c must give me the character corresponding to ascii 65
It should and if your machine is little-endian, it will, indeed. However, you're printing the 4th byte of your int using *(c + 3), that's still 0. Perhaps you meant *c instead?
The best would be not aliasing stuff through pointers, however. Integers have the nice property that they can be operated on by bitwise operators.
uint32_t i = 0x12345678;
uint8_t b0 = (i >> 0) & 0xff;
uint8_t b1 = (i >> 8) & 0xff;
uint8_t b2 = (i >> 16) & 0xff;
uint8_t b3 = (i >> 24) & 0xff;
This will give you access to the bytes correctly regardless to the endianness of sour architecture.

C - unsigned int to unsigned char array conversion

I have an unsigned int number (2 byte) and I want to convert it to unsigned char type. From my search, I find that most people recommend to do the following:
unsigned int x;
...
unsigned char ch = (unsigned char)x;
Is the right approach? I ask because unsigned char is 1 byte and we casted from 2 byte data to 1 byte.
To prevent any data loss, I want to create an array of unsigned char[] and save the individual bytes into the array. I am stuck at the following:
unsigned char ch[2];
unsigned int num = 272;
for(i=0; i<2; i++){
// how should the individual bytes from num be saved in ch[0] and ch[1] ??
}
Also, how would we convert the unsigned char[2] back to unsigned int.
Thanks a lot.
You can use memcpy in that case:
memcpy(ch, (char*)&num, 2); /* although sizeof(int) would be better */
Also, how would be convert the unsigned char[2] back to unsigned int.
The same way, just reverse the arguments of memcpy.
How about:
ch[0] = num & 0xFF;
ch[1] = (num >> 8) & 0xFF;
The converse operation is left as an exercise.
How about using a union?
union {
unsigned int num;
unsigned char ch[2];
} theValue;
theValue.num = 272;
printf("The two bytes: %d and %d\n", theValue.ch[0], theValue.ch[1]);
It really depends on your goal: why do you want to convert this to an unsigned char? Depending on the answer to that there are a few different ways to do this:
Truncate: This is what was recomended. If you are just trying to squeeze data into a function which requires an unsigned char, simply cast uchar ch = (uchar)x (but, of course, beware of what happens if your int is too big).
Specific endian: Use this when your destination requires a specific format. Usually networking code likes everything converted to big endian arrays of chars:
int n = sizeof x;
for(int y=0; n-->0; y++)
ch[y] = (x>>(n*8))&0xff;
will does that.
Machine endian. Use this when there is no endianness requirement, and the data will only occur on one machine. The order of the array will change across different architectures. People usually take care of this with unions:
union {int x; char ch[sizeof (int)];} u;
u.x = 0xf00
//use u.ch
with memcpy:
uchar ch[sizeof(int)];
memcpy(&ch, &x, sizeof x);
or with the ever-dangerous simple casting (which is undefined behavior, and crashes on numerous systems):
char *ch = (unsigned char *)&x;
Of course, array of chars large enough to contain a larger value has to be exactly as big as this value itself.
So you can simply pretend that this larger value already is an array of chars:
unsigned int x = 12345678;//well, it should be just 1234.
unsigned char* pChars;
pChars = (unsigned char*) &x;
pChars[0];//one byte is here
pChars[1];//another byte here
(Once you understand what's going on, it can be done without any variables, all just casting)
You just need to extract those bytes using bitwise & operator. OxFF is a hexadecimal mask to extract one byte. Please look at various bit operations here - http://www.catonmat.net/blog/low-level-bit-hacks-you-absolutely-must-know/
An example program is as follows:
#include <stdio.h>
int main()
{
unsigned int i = 0x1122;
unsigned char c[2];
c[0] = i & 0xFF;
c[1] = (i>>8) & 0xFF;
printf("c[0] = %x \n", c[0]);
printf("c[1] = %x \n", c[1]);
printf("i = %x \n", i);
return 0;
}
Output:
$ gcc 1.c
$ ./a.out
c[0] = 22
c[1] = 11
i = 1122
$
Endorsing #abelenky suggestion, using an union would be a more fail proof way of doing this.
union unsigned_number {
unsigned int value; // An int is 4 bytes long
unsigned char index[4]; // A char is 1 byte long
};
The characteristics of this type is that the compiler will allocate memory only for the biggest member of our data structure unsigned_number, which in this case is going to be 4 bytes - since both members (value and index) have the same size. Had you defined it as a struct instead, we would have 8 bytes allocated on memory, since the compiler does its allocation for all the members of a struct.
Additionally, and here is where your problem is solved, the members of an union data structure all share the same memory location, which means they all refer to same data - think of that like a hard link on GNU/Linux systems.
So we would have:
union unsigned_number my_number;
// Assigning decimal value 202050300 to my_number
// which is represented as 0xC0B0AFC in hex format
my_number.value = 0xC0B0AFC; // Representation: Binary - Decimal
// Byte 3: 00001100 - 12
// Byte 2: 00001011 - 11
// Byte 1: 00001010 - 10
// Byte 0: 11111100 - 252
// Printing out my_number one byte at time
for (int i = 0; i < (sizeof(my_number.value)); i++)
{
printf("index[%d]: %u, 0x%x\n", \
i, my_number.index[i], my_number.index[i]);
}
// Printing out my_number as an unsigned integer
printf("my_number.value: %u, 0x%x", my_number.value, my_number.value);
And the output is going to be:
index[0]: 252, 0xfc
index[1]: 10, 0xa
index[2]: 11, 0xb
index[3]: 12, 0xc
my_number.value: 202050300, 0xc0b0afc
And as for your final question, we wouldn't have to convert from unsigned char back to unsigned int since the values are already there. You just have to choose by which way you want to access it
Note 1: I am using an integer of 4 bytes in order to ease the understanding of the concept. For the problem you presented you must use:
union unsigned_number {
unsigned short int value; // A short int is 2 bytes long
unsigned char index[2]; // A char is 1 byte long
};
Note 2: I have assigned byte 0 to 252 in order to point out the unsigned characteristic of our index field. Was it declared as a signed char, we would have index[0]: -4, 0xfc as output.

How to get memory address in C and output it?

I need to get memory address and bits of index then I need to output index of the memory address. Can anyone help?
Given any variable in C, you can get its address using the "address-of" operator &:
int x;
int* addressOfX = &x;
You can print out addresses using the %p specifier in printf:
printf("%p\n", &x); // Print address of x
To access individual bits of an integer value, you can use the bitwise shifting operators, along with bitwise AND, to shift the bit you want to the proper position and then to mask out the other bits. For example, to get the 5th bit of x, you can write
int x;
int fifthBit = (x >> 4) & 0x1;
This shifts down the number 4 bits, leaving the fifth bit in the LSB spot. ANDing this value with 1 (which has a 1 bit in the lowest spot and 0 bits everywhere else) masks out the other bits and returns the value. For example:
int x = 31; // 11111
prtinf("%d\n", (x >> 4) & 0x1); // Prints 1
This worked for me ;)
// uses :: head
// ----------------------------------------------
#include <stdio.h>
// ----------------------------------------------
// func :: main
// ----------------------------------------------
int main()
{
void *fooz = "bar";
char addr[64];
sprintf(addr, "%p", &fooz);
// do some stuff with `addr`, or not :)
puts(addr);
return 0;
}
// ----------------------------------------------
Prints out something like: ~> 0x7ffdfb91d698

Resources