Saving double values in char[] buffer - c

I try to write program whitch uses stack for present some kind of data (char, double or string).
char *data_buffer;
double n;
...
data_buffer = (char*)malloc(4096 * sizeof(char));
...
*(data_buffer + buffer_top) = n; //buffer_top - just offset for first byte
...
printf("%f ", (double)*(data_buffer + buffer_top));
Variables data_buffer and buffer_top correct.
But output is strange. It correct only if n < 127.
Why could it be?
P.S. I don't want to change type of data_buffer becase it includes also char and string of different lengths.
Example of work (!! - test output of n before write it to buffer:
126 //push
!! 1.260000e+02
127 // push
!! 1.270000e+02
128 // push
!! 1.280000e+02
. // pop
-128.000000 //error
. //pop
127.000000 //ok
. //pop
126.000000 //ok
123456 // push
!! 1.234560e+05
. //pop
64.000000 //error

Both lines are missing a cast to (double *), so they do a char assignment and a read, respectively. Here's what your code is actually doing with some explicit (char) casts added to highlight the incorrect type conversions.
*(data_buffer + buffer_top) = (char) n;
...
printf("%f ", (double) (char) *(data_buffer + buffer_top));
What you want is:
*((double *) (data_buffer + buffer_top)) = n;
...
printf("%f ", *((double *) (data_buffer + buffer_top)));

Related

Accessing string that was passed as argument causes stack buffer overflow

I'm studying C at uni and am trying to access the string (the string representation of a binary-number) that was passed into a function to convert it into the integer-representation of that string.
Eg. "011" should return 3.
The string is the first 3 bits in a bitstream that's inputted in reverse.
char * temp_holder = (char *)malloc(sizeof(char) * 4);
int index_of_holder = 0;
for(int i = 2; i >= 0; i--){
printf("%c", buffer[i]);
temp_holder[index_of_holder] = buffer[i];
}
printf("\n");
int decimalValue = fromBinaryToInt(&temp_holder, 3);
printf("DECIMAL_VALUE: %d\n", decimalValue);
The fromBinaryToInt function is:
int fromBinaryToInt(char *string[], int length){
for(int i = 0; i < length; i++){
printf("%c", *string[i]);
}
int int_rep = strtol(*string, (char **)NULL, 2);
printf("REP: %d\n", int_rep);
return int_rep;
}
The subsequent error I get is:
==21==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffda9f47a08 at pc 0x000000500cdf bp 0x7ffda9f47980 sp 0x7ffda9f47978
- READ of size 8 at 0x7ffda9f47a08 thread T0
I thought this could be due to the null-terminating character so I played around with modifying the length variable (+/- 1) in the for-loop within fromBinaryToInt but that hasn't changed anything.
I also considered the for-loop only accessing the first element and nothing more - but my understanding is I've sent through the memory address and the length of the block so the for-loop should have access to the indexes.
Any help would be greatly appreciated,
Cheers :)
In this code:
int index_of_holder = 0;
for(int i = 2; i >= 0; i--){
printf("%c", buffer[i]);
temp_holder[index_of_holder] = buffer[i];
}
index_of_holder is never changed, so all the characters are put in temp_holder[0]. The rest of temp_holder remains uninitialized.
This:
int fromBinaryToInt(char *string[], int length)
declares string to be an array of pointers to char. It is indeed passed &temp_holder, which may be considered to be a pointer to the first element of an array of one pointer to char. However, a more normal usage is to declare a simple pointer to char
int fromBinaryToInt(char *string, int length)
and pass it temp_holder, as in fromBinaryToInt(temp_holder, 3).
As it is, where it is used here:
printf("%c", *string[i]);
This takes element i of the array. When i is 0 in the loop, that is fine, it takes the first element, which exists and is a pointer to char, and then deferences it with * and prints that. However, when i is 1, it attempts to take the second element of the array. That element does not exist, and the resulting behavior is undefined.
If the parameter were merely char *string, then this printf could be:
printf("%c", string[i]);
and, in calling strtol, you would simply pass string rather than *string:
int int_rep = strtol(string, (char **)NULL, 2);
Firstly, bug in below line, index_of_holder remains same all the time, please increment it.
temp_holder[index_of_holder] = buffer[i];
Secondly, in fromBinaryToInt() string is single pointer only so you can't do *string[i]); in the next printf statement.
Here is the working code
int fromBinaryToInt(char *string, int length){
for(int i = 0; i < length; i++){
printf("%c", string[i] ); /*since string is single pointer now you can do like before you did */
}
int int_rep = strtol(string, (char **)NULL, 2);
printf("REP: %d\n", int_rep);
return int_rep;
}
int main() {
char * temp_holder = (char *)malloc(sizeof(char) * 4);
char buffer[4] ="011";
int index_of_holder = 0;
for(int i = 2; i >= 0; i--){
printf("%c", buffer[i]);
temp_holder[index_of_holder] = buffer[i];
index_of_holder++;
}
printf("\n");
int decimalValue = fromBinaryToInt(temp_holder, 3);/* no need to pass address of temp_holder */
printf("DECIMAL_VALUE: %d\n", decimalValue);
return 0;
}

What does *(int*)&variable means?

I am generating arrays which are dynamic size. The part of the code that I am showing is grabbing value of the array the way it does, and it works.
The problem is I have no idea how this work. I don't see why both cast and pre-cast have pointer in it?
How to code something similar correctly?
Example: *(double*)&j;
I also noticed that *(int*)&column_sum[i] + 1; won't add the 1 to the result. Also I have no idea why...
double val = 1000 * multiplier;
double *column_sum = malloc(val * sizeof *column_sum);
double *p = malloc(val * val * sizeof *p);
printf("Rows/Columns: %.0f", val);
for (i = 0; i < val; i++){
column_sum[i] = 0.0;
for (j = 0; j < val; j++){
int index = i * (int)val + j;
p[index] = *(double*)&j; // here
int offsetI = *(int*)&column_sum[i] + 1; // here
int offsetJ = *(int*)&p[index] + 1; // here
printf("%d->", offsetI);
printf("%d,", offsetJ);
}
printf("\n");
}
What does it do:
&var // get the pointer of the variable
(type*)&var // cast the pointer to an other pointer type
*(type*)&var // Dereferencing the casted pointer so "interpret" the variable as a "type"
What is important here, is that it is interpret and not cast.
We can see the difference in this example:
float a = 0.5;
int b = (int)a;
int c = *(int*)&a;
printf("%f %08x %08x\n", a, b, c);
// Output:
// 0.500000 00000000 3f000000
// 3f000000 is the way 0.5 is encoding following standard IEEE 754
It's usefull if you want to work on representation of floats for example:
float a = 1.5;
int b = *(int*)&a;
b &= 0xF;
a = *(float*)&b;
For example it's the reason of the use of this syntax here: https://en.wikipedia.org/wiki/Fast_inverse_square_root#Overview_of_the_code, for manipulating bit of representation of double.

integers in char array

I want know how integers are treated in char arrays. For example when we use scanf() & printf() functions for single characters we use "%c", for string values "%s", etc. I used "%s" for printing the char array with integers. But it prints some junk characters as the output.
While working with integer variables directly, it's simple as:
int i = 7;
printf("%d", i);
and while working with an array of characters, you could create helper functions that will do the conversion between char* <-> int so that you end up with more portable solution:
int toInt(unsigned char* p) {
return *(p + 0) << 24 | *(p + 1) << 16 | *(p + 2) << 8 | *(p + 3);
}
...
unsigned char arr[4] = {0,0,0,4};
int i = toInt(&arr[0]);
printf("%d", i);
should print 4
Alternatively you might use simple cast:
unsigned char arr[4] = {0,0,0,4};
int* i = &arr[0];
printf("%d", *i);
but that solution will be depend on endianness. On ideone.com it prints 67108864.
If you know the length of each phone number will be the same, you could pad out the front of the number with zeros. e.g. to pad each number out to 10 digits, putting 0's in front when necessary:
int d = 123456789;
printf("%d\n", d); // prints 123456789
printf("%010d\n", d); // prints 0123456789
d = 12345678;
printf("%010d\n", d); // prints 0012345678 :-(
It's hard to guess more about the requirements without seeing the code. There's lots of examples of formatting with printf, eg: http://www.codingunit.com/printf-format-specifiers-format-conversions-and-formatted-output

memcpy() with different data types

Trying to copy A into B....
char *A;
double *B;
unsigned int size = 1024;
A = malloc (size*size * sizeof (char));
B = malloc (size*size * sizeof (double));
//fill A here
memcpy (B, &A[0], (size*size * sizeof (char)));
Printing values in B don't match whats in A.
What's going wrong?
Thanks for any help!
Edit: The point of this is to test the memcpy function's speed in relation to the size of the L2 cache. I'm just wanting to make sure the code above is actually copying all of A into B. Sorry about leaving out this info: I just try to make it as simple as possible (and went too far this time)
It's hard to tell exactly what you are trying to do.
How are you printing values? Print routines like printf also depend on the type.
It sounds like you just want to get float input values. This can be done using the scanf family.
int num_floats = 10;
double* B = malloc (num_floats * sizeof (double));
int count;
for (count = 0; count < num_floats; count++)
{
printf("Insert float %d: ", count);
scanf("%f", &B[num_floats]);
}
for (count = 0; count < num_floats; count++)
{
printf("Float %d: %f", B[num_floats]);
}
free(B);
If you are trying to convert C-strings from char * to floating point numbers and don't want to use sscanf, you can also use atof.
const char* num_str = "1.01";
double num = atof(num_str);

Transferring values from void pointer

Can someone tell me whats wrong with this code?
base is a void pointer to a bunch of floats
i is a value >1
size is the size of the type (in this case float - 4 )
char *a = (char *)base;
char *temp = (char *)a + size * (i/2);
printf("%d: %d = ", i, temp);
memcpy(a + size * i , temp , size);
printf("%d\n", a + size * i);
This is the output:
2: 136724 = 136728
3: 136724 = 136732
4: 136728 = 136736
6: 136732 = 136744
7: 136732 = 136748
8: 136736 = 136752
If a was a void*, the compiler wouldn't allow you to write a + size*i (you can't do pointer arithmetic with incomplete types). Probably the type isn't what you think it is.
But why do you think there's a problem? The left-hand column advances half as fast as the right-hand column, and this is expected because you are dividing by 2.
You do realize that you're printing addresses, and not the values being copied, right?
char *a = (char *)base;
char *temp = (char *)a + size * (i/2);
printf("%d: %f = ", i, *(float *)temp);
memcpy(a + size * i , temp , size);
printf("%f\n", *(float *)(a + size * i));
The changes I have made are to dereference the pointers correctly (and casting them to the correct type) and to change %d to %f as you specified that base is an array of floats. %d is for ints and %f is for floats.
The reason your code did not work is that you were printing out the addresses and not the values.
Would you please tell us what you're trying to accomplish? Seems like a
homework problem, right?
The C language allows you to cast any pointer to a void*, and then cast it
back to the original pointer type, without losing any information. Anything
else you do with a void pointer is a bad idea, although some library functions
(such as memcpy) still have void* for historical reasons. That's also why
you don't need an explicit cast to go from any pointer type to a void*.
You cannot look at what the void* points to, until you cast it back to the
correct pointer type. And be careful when you do!
#include <stdio.h>
#include <memory.h>
/* It's a bad idea to pass Base as a void pointer,
but that's what you said you have. */
void silly_function(void*base, int i, int size) {
/* Using a char* that points to float, is an even worse idea!
char *a = (char *)base;
char *temp = (char *)a + size * (i/2);
printf("%d: %d = ", i, temp);
memcpy(a + size * i , temp , size);
printf("%d\n", a + size * i);
**/
/** Probably ought to have a big SWITCH statement here, based
on the data type. sizeof() isn't a good way to do this...
On many computers, sizeof(float)==sizeof(long), but that
doesn't mean that a float* is the same as a long* !!!
For now, I'm going to assume (as you did) that base points
to an array of float. */
/* I think you're trying to copy the first half of the array
into the second half of the array! But that's easy. */
float*firsthalf = (float*)base;
float*secondhalf = firsthalf + (i/2);
/* Show some starting values. */
printf("Before: %x --> %f, %x --> %f\n",
firsthalf, *firsthalf, secondhalf, *secondhalf);
/* Now do the copy */
memcpy(secondhalf, firsthalf, (i/2)*(sizeof(float)));
/* Now prove that it's been copied? */
printf("After: %x --> %f, %x --> %f\n",
firsthalf, *firsthalf, secondhalf, *secondhalf);
}
int main() {
/* This drives the test */
float ary[10] = {
1.1f, 2.2f, 3.3f, 4.4f, 5.5f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
silly_function(ary, 10, sizeof(ary[0]));
return 0;
}
On my system, the output is
Before: 12ff38 --> 1.100000, 12ff4c --> 0.000000
After: 12ff38 --> 1.100000, 12ff4c --> 1.100000
I hope this helps.

Resources