I am creating a 2D array using malloc and when I iterate through the array there are characters and symbols that I do not want in there. Shouldn't the array be completely empty?
I have tried to assign the null character to the beginning of each row but that doesn't change anything.
char **structure;
structure = malloc(sizeof *structure * 2);
if (structure) {
for (size_t i = 0; i < 2; i++) {
structure[i] = malloc(sizeof *structure[i] * 20);
structure[i][0] = '\0';
}
}
for (int i = 0; i <= 2; i++) {
for (int j = 0; j < 20; j++) {
printf("%c ", structure[i][j]);
}
printf("\n");
}
I expected the output to just be blank spaces but this is what appeared:
Z Ñ P Ñ l L O
Z Ñ P Ñ N U M B
You should use the calloc function; this is what I often use. It does the same work as malloc() but it initializes all allocated bits with 0.
calloc documentation
As you are accessing each character you must clear all position explicitly to get your desired output.
char **structure;
structure = (char**)malloc( (sizeof *structure) * 2 );
if (structure)
{
for(size_t i = 0; i < 2; i++){
// structure[i];
structure[i] =(char *) malloc( sizeof *structure[i] * 20 );
for(int j=0; j<20; j++)
structure[i][j] = '\0';
}
}
for(int i = 0; i < 2; i++){ //you can not access position i==2
for(int j = 0; j < 20; j++)
{
printf("%c ", structure[i][j]);
}
printf("\n");
}
You can also use printf("%s", structure[i]) to make it work with your current code. it will work because you have made first position of both strings NULL('\0').So printf function will terminate for both character arrays without printing anything. But remember, other position than the first one of both arrays will contain garbage value.
When you are allocating memory the data inside the memory is undefined. the malloc function just giving you the memory.
if you want the memory to be initialized to 0 you can always use the standard calloc function.
If you want to initialize it after allocation you can always use the memset function. in your case
memset(structure, 0, (sizeof *structure) * 2)
You are not really allocating a 2D array of char, but an array of 2 pointers to arrays of 20 char. It is much simpler to allocate a true 2D array:
// allocate a 2D array and initialize it to null bytes
char (*structure)[20] = calloc(sizeof(*structure), 2);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 20; j++) {
printf("%02X ", structure[i][j]);
}
printf("\n");
}
Output:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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 last month.
Improve this question
I am streaming a video in python via WebSocket, which is a raw bytes stream and appears like this:
b'\x00\x00\x00\x01A\x9a \x02\x04\xe1{=z\xf8FMS\xe6\\\x9eMubH\xa7R.1\xd7]F\xea3}\xa9b\x9f\x14n\x12| ....'
Now, I am passing these bytes to a C function (via ctypes) where I am trying to convert this to a uint8_t [] array (This is needed in order to decode it using a FFmpeg library). Here's my code so far:
This is how I am passing bytes to C:
import ctypes
dll = ctypes.CDLL("decode_video.so")
data = bytearray(b'\x00\x00\x00\x01A\x9a \x02\x04\xe1-{=z\xf8FM....')
b_array = ctypes.c_char * len(data)
dll.conversion_test(b_array.from_buffer(data), len(data))
decode_video.c
void conversion_test(unsigned char* buf, int bufSize) {
char temp[3];
uint8_t vals[bufSize];
// Iterate over the values
for (int i = 0; i < bufSize; i++) {
// Copy two characters into the temporary string
temp[0] = buf[i * 2];
temp[1] = buf[i * 2 + 1];
temp[2] = 0;
vals[i] = strtol(temp, NULL, 16);
}
for(int i=0; i<bufSize; i++){
printf("%02x ", vals[i] & 0xff);
}
}
Aside from this, I am simultaneously dumping the stream to a file. In C, I have another function that reads from this file and stores in a uint8_t buffer.
Streaming code in python:
f = open("video.h264", "wb")
def on_message(ws, message):
# The first 14 characters have irrelevant info to decode the video
f.write(message[14:])
ws = websocket.WebSocketApp("wss://somewebsite.com/archives",
on_open=on_open,
on_message=on_message,
on_error=on_error,
on_close=on_close,
header=[protocol_str]
)
ws.binaryType = 'arraybuffer'
ws.run_forever(dispatcher=rel)
Reading from the raw file in C:
#include "libavcodec/avcodec.h"
#define INBUF_SIZE 4096
uint8_t *data;
uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
f = fopen(input_name, "rb");
data_size = fread(inbuf, 1, INBUF_SIZE, f);
// Printing bytes in hex to debug
for(size_t i=0; i<data_size; i++){
printf("%02x ", inbuf[i] & 0xff);
}
However the contents of this inbuf and output of the vals buffer are not the same. Basically, I am unsure of my method of passing bytes to C and its corresponding coversion to uint8_t.
Update:
I tried printing the hex values of vals and here's what it looks like:
00 00 0a 00 00 00 00 00 00 00 00 00 00 00 01 00 00 ...
While the output of inbuf looks like this:
00 00 00 01 67 42 00 1e e2 90 14 07 b6 02 dc ...
Fix:
As suggested by #n. m. and #dreamlax, a simple identity mapping works between unsigned char and uint8_t. Now vals and inbuf output the same values!
void conversion_test(unsigned char* buf, int bufSize) {
uint8_t vals[bufSize];
for(int i = 0; i < bufSize; i++)
vals[i] = (uint8_t)buf[i];
}
(OR) A simple type-casting
uint8_t *vals = (uint8_t *)ubuf;
I found this piece of code in my C programming book:
int i = 42;
int *p;
p = &i; // & is address of sign
*p = i; // * is dereference sign
Is there any difference between "p = &i" and "*p = i"??
Will "p" have different characteristics while using these two expressions???
Edit: Because this code is just trying to explain the concept of the pointer, it is not runnable... So the order of these two assignments is not relevant in this case... Sorry for making things vague...
Is there any differences between “p = &i” and “*p = i” while assigning the address int “i” to a pointer “p”
Yes, there is a huge difference. Only p = &i means "assign the address of i to p".
On the other hand *p = i means "assign the value of i to the value at the address that is stored in p". You can see the results with a simple example:
int i = 42;
int* p;
p = &i;
printf("%d", i);
*p = 5;
printf("%d", i);
int j = 3;
printf("%d %d", i, j);
p = &j;
*p = i;
printf("%d %d", i, j);
First, a quick summary - given the declaration
int i, *p;
and the statement
p = &i;
then the following are true:
p == &i // int * == int *
*p == i // int == int
You've assigned the address of i to p. Thus, the expressions *p and i evaluate to the same thing. Assigning a value to *p is the same as assigning a value to i, reading a value from *p is the same as reading a value from i. If you later did something like
*p = 10;
Then this is the same things as writing
i = 10;
IOW, you're assigning a new value to the thing p points to.
If we introduce multiple levels of indirection, like:
int i;
int *p = &i;
int **q = &p;
then the following are all true:
q == &p // int ** == int **
*q == p == &i // int * == int * == int *
**q == *p == i // int == int == int
Thus, writing to **q is the same as writing to *p is the same as writing to i. Writing to *q is the same as writing to p.
The following may or may not be helpful.
I've written a small utility that displays the contents of various items in memory, and I'm going to use that to illustrate the difference between p = &i and *p = i.
First, here's the test program:
#include <stdio.h>
#include "dumper.h"
int main( void )
{
int i = 0, j = 0, *p = NULL;
char *names[] = { "i", "j", "p", "*p"};
void *addrs[] = { &i, &j, &p, NULL };
size_t sizes[] = { sizeof i, sizeof j, sizeof p, sizeof *p };
puts( "Before any assignments: ");
dumper( names, addrs, sizes, 3, stdout );
p = &i;
addrs[3] = p;
puts( "After p = &i: " );
dumper( names, addrs, sizes, 4, stdout );
*p = 42;
puts( "After *p = 42: " );
dumper( names, addrs, sizes, 4, stdout );
p = &j;
addrs[3] = p;
puts( "After p = &j: " );
dumper( names, addrs, sizes, 4, stdout );
*p = 10;
puts( "After *p = 10: " );
dumper( names, addrs, sizes, 4, stdout );
return 0;
}
The dumper function displays the state of the various objects in memory at that time.
So, we start with the declarations:
int i = 0, j = 0, *p = 0;
i and j are regular ints, p is a pointer to int. That means the values stored in p are the addresses of other int objects. Here's what things look like in memory at this point:
Item Address 00 01 02 03
---- ------- -- -- -- --
i 0x7ffee3d07a28 00 00 00 00 ....
j 0x7ffee3d07a24 00 00 00 00 ....
p 0x7ffee3d07a18 00 00 00 00 ....
0x7ffee3d07a1c 00 00 00 00 ....
i occupies 4 bytes starting at address 0x7ffee3d07a281, j occupies four bytes starting at address 0x7ffee3d07a24, and p occupies eight bytes starting at address 0x7ffee3d07a18. All three objects currently store 0 values.
Next, we execute the statement
p = &i;
This stores the address of i to p. Here's how things look afterward:
Item Address 00 01 02 03
---- ------- -- -- -- --
i 0x7ffee3d07a28 00 00 00 00 ....
j 0x7ffee3d07a24 00 00 00 00 ....
p 0x7ffee3d07a18 28 7a d0 e3 (z..
0x7ffee3d07a1c fe 7f 00 00 ....
*p 0x7ffee3d07a28 00 00 00 00 ....
Instead of storing all zeros, p now stores the address of i2. Notice that the expression *p has the same effective address as the object i3.
Now we execute the statement
*p = 42;
Here's how our memory looks now:
Item Address 00 01 02 03
---- ------- -- -- -- --
i 0x7ffee3d07a28 2a 00 00 00 *...
j 0x7ffee3d07a24 00 00 00 00 ....
p 0x7ffee3d07a18 28 7a d0 e3 (z..
0x7ffee3d07a1c fe 7f 00 00 ....
*p 0x7ffee3d07a28 2a 00 00 00 *...
The least significant byte of i now stores the value 0x2a, which is 42 in hexadecimal. Note that *p shows the same thing. Again, in most circumstances, *p is equivalent to i.
Now, we assign the address of j to p:
p = &j;
Here's the state of the world now:
Item Address 00 01 02 03
---- ------- -- -- -- --
i 0x7ffee3d07a28 2a 00 00 00 *...
j 0x7ffee3d07a24 00 00 00 00 ....
p 0x7ffee3d07a18 24 7a d0 e3 $z..
0x7ffee3d07a1c fe 7f 00 00 ....
*p 0x7ffee3d07a24 00 00 00 00 ....
p now stores j's address, and *p is now equivalent to j. We finish up by assigning 10 to *p:
*p = 10;
which leaves us with
Item Address 00 01 02 03
---- ------- -- -- -- --
i 0x7ffee3d07a28 2a 00 00 00 *...
j 0x7ffee3d07a24 0a 00 00 00 ....
p 0x7ffee3d07a18 24 7a d0 e3 $z..
0x7ffee3d07a1c fe 7f 00 00 ....
*p 0x7ffee3d07a24 0a 00 00 00 ....
j now stores the value 0x0a, which is hex for 10. Again, the expression *p is equivalent to j.
On most systems, the address will change from run to run, so don't get too hung up on the exact address value.
x86 is little-endian, so the least significant byte is the addressed byte. This means values read "backwards" - left to right, bottom to top.
This is a bit of dramatic license - expressions don't have addresses as such. This is just to illustrate that the expression *p is effectively the same as i in most circumstances.
I wrote this code to merge two sorted arrays. The desired output is:
Merged array:0 1 2 3 4 5 6 7 8 9 10 11 12
I am using gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 to compile my code.
The problem is that sometimes I get the desired output when I execute the a.out file but on other occasions, the cursor keeps blinking and no result is shown. Why is this happening? Is there something wrong with my code?
#include<stdio.h>
#include<stdlib.h>
int main(void){
//change arrays as per your need but it should be sorted
int a[] = {1,2,3,7,8};
int b[] = {0,3,5,6,9,10,11,12};
int m =sizeof(a) / sizeof(int);
int n =sizeof(b) / sizeof(int);
int index=0, j=0, k=0;
int size = m + n;
int array[size];
while(index < size) {
while(a[j] < b[k] && j<m ){
array[index] = a[j];
++index;
++j;
}
while(a[j] > b[k] && k<n){
array[index] = b[k];
++index;
++k;
}
while(a[j] == b[k]){
array[index] = a[j];
j++; index++;
}
}
printf("Merged array: ");
for(int i=0; i<size; i++)
printf("%d ", array[i]);
printf("\n");
}
You have undefined behaviour (accessing the array out of bounds). Use gcc -fsanitize=undefined to create an executable that can detect all sorts of bad behaviour.
% gcc -g fffff.c -Wall -Wextra -fsanitize=undefined
% ./a.out
fffff.c:20:12: runtime error: index 5 out of bounds for type 'int [5]'
fffff.c:20:12: runtime error: load of address 0x7ffd0c0c9804 with insufficient space for an object of type 'int'
0x7ffd0c0c9804: note: pointer points here
08 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 00 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00
^
fffff.c:25:12: runtime error: index 5 out of bounds for type 'int [5]'
fffff.c:25:12: runtime error: load of address 0x7ffd0c0c9804 with insufficient space for an object of type 'int'
0x7ffd0c0c9804: note: pointer points here
08 00 00 00 04 00 00 00 04 00 00 00 04 00 00 00 00 00 00 00 03 00 00 00 05 00 00 00 06 00 00 00
^
fffff.c:30:12: runtime T: index 5 out of bounds for type 'int [5]'
fffff.c:30:12: runtime error: load of address 0x7ffd0c0c9804 with insufficient space for an object of type 'int'
0x7ffd0c0c9804: note: pointer points here
08 00 00 00 04 00 00 00
The lines 20, 25 and 30 are
20 while(a[j] < b[k] && j<m ){
25 while(a[j] > b[k] && k<n){
30 while(a[j] == b[k]){
Is there something wrong with my code?
Yes!
It gets out of bounds when accessing a, here for example:
while(a[j] < b[k] && j<m ){
array[index] = a[j];
++index;
++j;
}
j will eventually get the value 4, enter the body of the if statement, and when it tries to resolve the condition of the while loop, it will access a[5], which is out of bounds, thus causing Undefined Behavior (which explains why your code runs sometimes, and others hang).
You could let short circuiting help you by changing your while loop's condition to this:
while(j < m && a[j] < b[k]) {
which when j reaches mm, resulting in j<m evaluated to false, will not go through a[j] < b[k], because a logical and operation will be false, if at least one of its operands are false.
Same happens in your next while loop. So change it to this:
while(k < n && a[j] > b[k]) {
Last, but not least, the condition of the last while loop:
while(a[j] == b[k]){
will also invoke Undefined Behavior, since j will be equal to 5, and k equal to 8.
Changing it to:
while(j < m && k < n && a[j] == b[k]) {
will prevent Undefined Behavior from being invoked.
I've written in a file (using 'fwrite()') the following:
TUS�ABQ���������������(A����������(A��B������(A��B���A��(A��B���A������B���A������0����A������0�ABQ�������0�ABQ�����LAS����������������A�����������A��&B�������A��&B��B���A��&B��B������&B��
B����153���B����153�LAS�����153�LAS�����LAX���������������:A����������:AUUB������:AUUB��B��:
AUUB��B����UUB��B����������B��������LAX���������LAX�����MDW���������������A����������A��(�������A��(����A��A��(����A������(����A����A�89���A����A�89MDW�����A�89MDW�����OAK���������
����������������������#�����������#�����������#�����������#�������������������������OAK���������OAK�����SAN���������������LA����������LA��P#������LA��P#��#A��LA��P#��#A������P#��#A����������#A��������SAN���������SAN�����TPA�ABQ����������������B�����������B��#�����...(continues)
which is translated to this:
TUSLWD2.103.47.775.1904.06.40.03AMBRFD4.63.228.935.0043.09.113.0ASDGHU5.226.47.78.3.26...(The same structure)
and the hexdump of that would be:
00000000 54 55 53 00 41 42 51 00 00 00 00 00 00 00 00 00 |TUS.ABQ.........|
00000010 00 00 00 00 00 00 28 41 00 00 0e 42 00 00 f8 41 |......(A...B...A|
00000020 00 00 00 00 4c 41 53 00 00 00 00 00 00 00 00 00 |....LAS.........|
00000030 00 00 00 00 00 00 88 41 00 00 26 42 9a 99 11 42 |.......A..&B...B|
(Continues...)
the structure is, always 2 words of 3 characters each one (i.e. TUS and LWD) followed by 7 floats, and then it repeats again on a on until end of file.
The key thing is: I just want to read every field separated like 'TUS', 'LWD', '2.10', '3.4', '7.77'...
And I can only use 'fread()' to achieve that! For now, I'm trying this:
aux2 = 0;
fseek(fp, SEEK_SET, 0);
fileSize = 0;
while (!feof(fp) && aux<=2) {
fread(buffer, sizeof(char)*4, 1, fp);
printf("%s", buffer);
fread(buffer, sizeof(char)*4, 1, fp);
printf("%s", buffer);
for(i=0; i<7; i++){
fread(&delay, sizeof(float), 1, fp);
printf("%f", delay);
}
printf("\n");
aux++;
fseek(fp,sizeof(char)*7+sizeof(float)*7,SEEK_SET);
aux2+=36;
}
And I get this result:
TUSABQ0.0000000.0000000.00000010.5000000.0000000.00000010.500000
AB0.0000000.000000-10384675421112248092159136000638976.0000000.0000000.000000-10384675421112248092159136000638976.0000000.000000
AB0.0000000.000000-10384675421112248092159136000638976.0000000.0000000.000000-10384675421112248092159136000638976.0000000.000000
But it does not works correctly...
*Note: forget the arguments of the last 'fseek()', cos I've been trying too many meaningless things!
To write the words (i.e. TUS) into the file, I use this:
fwrite(x->data->key, 4, sizeof(char), fp);
and to write the floats, this:
for (i = 0; i < 7; i++) {
fwrite(¤t->data->retrasos[i], sizeof(float), sizeof(float), fp);
}
I'd recommend using a structure to hold each data unit:
typedef struct {
float value[7];
char word1[5]; /* 4 + '\0' */
char word2[5]; /* 4 + '\0' */
} unit;
To make the file format portable, you need a function that packs and unpacks the above structure to/from a 36-byte array. On Intel and AMD architectures, float corresponds to IEEE-754-2008 binary32 format in little-endian byte order. For example,
#define STORAGE_UNIT (4+4+7*4)
#if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
size_t unit_pack(char *target, const size_t target_len, const unit *source)
{
size_t i;
if (!target || target_len < STORAGE_UNIT || !source) {
errno = EINVAL;
return 0;
}
memcpy(target + 0, source->word1, 4);
memcpy(target + 4, source->word2, 4);
for (i = 0; i < 7; i++)
memcpy(target + 8 + 4*i, &(source->value[i]), 4);
return STORAGE_UNIT;
}
size_t unit_unpack(unit *target, const char *source, const size_t source_len)
{
size_t i;
if (!target || !source || source_len < STORAGE_UNIT) {
errno = EINVAL;
return 0;
}
memcpy(target->word1, source, 4);
target->word1[4] = '\0';
memcpy(target->word2, source + 4, 4);
target->word2[4] = '\0';
for (i = 0; i < 7; i++)
memcpy(&(target->value[i]), source + 8 + i*4, 4);
return STORAGE_UNIT;
}
#else
#error Unsupported architecture!
#endif
The above only works on Intel and AMD machines, but it is certainly easy to extend to other architectures if necessary. (Almost all machines currently use IEEE 754-2008 binary32 for float, only the byte order varies. Those that do not, typically have C extensions that do the conversion to/from their internal formats.)
Using the above, you can -- should! must! -- document your file format, for example as follows:
Words are 4 bytes encoded in UTF-8
Floats are IEEE 754-2008 binary32 values in little-endian byte order
A file contains one or more units. Each unit comprises of
Name Description
word1 First word
word2 Second word
value0 First float
value1 Second float
value2 Third float
value3 Fourth float
value4 Fifth float
value5 Sixth float
value6 Second float
There is no padding.
To write an unit, use a char array of size STORAGE_UNIT as a cache, and write that. So, if you have unit *one, you can write it to FILE *out using
char buffer[STORAGE_UNIT];
if (unit_pack(buffer, sizeof buffer, one)) {
/* Error! Abort program! */
}
if (fwrite(buffer, STORAGE_UNIT, 1, out) != 1) {
/* Write error! Abort program! */
}
Correspondingly, reading from FILE *in would be
char buffer[STORAGE_UNIT];
if (fread(buffer, STORAGE_UNIT, 1, in) != 1) {
/* End of file, or read error.
Check feof(in) or/and ferror(in). */
}
if (unit_unpack(one, buffer, STORAGE_UNIT)) {
/* Error! Abort program! */
}
If one is an array of units, and you are writing or reading one[k], use &(one[k]) (or equivalently one + k) instead of one.
I am trying to write a code in C that generates a random integer , performs simple calculation and then I am trying to print the values of the file in IEEE standard. But I am unable to do so , Please help.
I am unable to print it in Hexadecimal/Binary which is very important.
If I type cast the values in fprintf, I am getting this Error expected expression before double.
int main (int argc, char *argv) {
int limit = 20 ; double a[limit], b[limit]; //Inputs
double result[limit] ; int i , k ; //Outputs
printf("limit = %d", limit ); double q;
for (i= 0 ; i< limit;i++)
{
a[i]= rand();
b[i]= rand();
printf ("A= %x B = %x\n",a[i],b[i]);
}
char op;
printf("Enter the operand used : add,subtract,multiply,divide\n");
scanf ("%c", &op); switch (op) {
case '+': {
for (k= 0 ; k< limit ; k++)
{
result [k]= a[k] + b[k];
printf ("result= %f\n",result[k]);
}
}
break;
case '*': {
for (k= 0 ; k< limit ; k++)
{
result [k]= a[k] * b[k];
}
}
break;
case '/': {
for (k= 0 ; k< limit ; k++)
{
result [k]= a[k] / b[k];
}
}
break;
case '-': {
for (k= 0 ; k< limit ; k++)
{
result [k]= a[k] - b[k];
}
}
break; }
FILE *file; file = fopen("tb.txt","w"); for(k=0;k<limit;k++) {
fprintf (file,"%x\n
%x\n%x\n\n",double(a[k]),double(b[k]),double(result[k]) );
}
fclose(file); /*done!*/
}
If your C compiler supports IEEE-754 floating point format directly (because the CPU supports it) or fully emulates it, you may be able to print doubles simply as bytes. And that is the case for the x86/64 platform.
Here's an example:
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <float.h>
void PrintDoubleAsCBytes(double d, FILE* f)
{
unsigned char a[sizeof(d)];
unsigned i;
memcpy(a, &d, sizeof(d));
for (i = 0; i < sizeof(a); i++)
fprintf(f, "%0*X ", (CHAR_BIT + 3) / 4, a[i]);
}
int main(void)
{
PrintDoubleAsCBytes(0.0, stdout); puts("");
PrintDoubleAsCBytes(0.5, stdout); puts("");
PrintDoubleAsCBytes(1.0, stdout); puts("");
PrintDoubleAsCBytes(2.0, stdout); puts("");
PrintDoubleAsCBytes(-2.0, stdout); puts("");
PrintDoubleAsCBytes(DBL_MIN, stdout); puts("");
PrintDoubleAsCBytes(DBL_MAX, stdout); puts("");
PrintDoubleAsCBytes(INFINITY, stdout); puts("");
#ifdef NAN
PrintDoubleAsCBytes(NAN, stdout); puts("");
#endif
return 0;
}
Output (ideone):
00 00 00 00 00 00 00 00
00 00 00 00 00 00 E0 3F
00 00 00 00 00 00 F0 3F
00 00 00 00 00 00 00 40
00 00 00 00 00 00 00 C0
00 00 00 00 00 00 10 00
FF FF FF FF FF FF EF 7F
00 00 00 00 00 00 F0 7F
00 00 00 00 00 00 F8 7F
If IEEE-754 isn't supported directly, the problem becomes more complex. However, it can still be solved.
Here are a few related questions and answers that can help:
How do I handle byte order differences when reading/writing floating-point types in C?
Is there a tool to know whether a value has an exact binary representation as a floating point variable?
C dynamically printf double, no loss of precision and no trailing zeroes
And, of course, all the IEEE-754 related info can be found in Wikipedia.
Try this in your fprint part:
fprintf (file,"%x\n%x\n%x\n\n",*((int*)(&a[k])),*((int*)(&b[k])),*((int*)(&result[k])));
That would translate the double as an integer so it's printed in IEEE standard.
But if you're running your program on a 32-bit machine on which int is 32-bit and double is 64-bit, I suppose you should use:
fprintf (file,"%x%x\n%x%x\n%x%x\n\n",*((int*)(&a[k])),*((int*)(&a[k])+1),*((int*)(&b[k])),*((int*)(&b[k])+1),*((int*)(&result[k])),*((int*)(&result[k])+1));
In C, there are two ways to get at the bytes in a float value: a pointer cast, or a union. I recommend a union.
I just tested this code with GCC and it worked:
#include <stdio.h>
typedef unsigned char BYTE;
int
main()
{
float f = 3.14f;
int i = sizeof(float) - 1;
BYTE *p = (BYTE *)(&f);
p[i] = p[i] | 0x80; // set the sign bit
printf("%f\n", f); // prints -3.140000
}
We are taking the address of the variable f, then assigning it to a pointer to BYTE (unsigned char). We use a cast to force the pointer.
If you try to compile code with optimizations enabled and you do the pointer cast shown above, you might run into the compiler complaining about "type-punned pointer" issues. I'm not exactly sure when you can do this and when you can't. But you can always use the other way to get at the bits: put the float into a union with an array of bytes.
#include <stdio.h>
typedef unsigned char BYTE;
typedef union
{
float f;
BYTE b[sizeof(float)];
} UFLOAT;
int
main()
{
UFLOAT u;
int const i = sizeof(float) - 1;
u.f = 3.14f;
u.b[i] = u.b[i] | 0x80; // set the sign bit
printf("%f\n", u.f); // prints -3.140000
}
What definitely will not work is to try to cast the float value directly to an unsigned integer or something like that. C doesn't know you just want to override the type, so C tries to convert the value, causing rounding.
float f = 3.14;
unsigned int i = (unsigned int)f;
if (i == 3)
printf("yes\n"); // will print "yes"
P.S. Discussion of "type-punned" pointers here:
Dereferencing type-punned pointer will break strict-aliasing rules