If I use
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream ),
how can I derefence the data pointed by ptr?. Like if I have
int main()
{
void *ptr
fread(ptr,1,100,file);
printf("%s",ptr);
}
You misunderstand the purpose of void * ptr in the declaration of fread.
From http://en.cppreference.com/w/c/io/fread
buffer - pointer to the array where the read objects are stored
First, the argument must be a valid pointer where objects can be stored. Using
void *ptr;
fread(ptr,1,100,file);
will lead to undefined behavior since ptr does not point to anything valid.
Second, the reason for the argument type is void* to allow you to read all kinds of data from a stream. E.g.
// Read an integer
int i;
fread(&i, sizeof(int), 1, file);
// Read 10 integers
int a[10];
fread(a, sizeof(int), 10, file);
// Read a double
double d;
fread(&d, sizeof(double), 1, file);
Related
I need to create a function that helps to implement a 2D array using linear storage in C++. The first of these functions is two_d_store(), which takes as arguments the following: base address in memory of region to be used as 2D array, size in bytes of an array entry, 2 array dimensions, and 2 index values. So with this two_d_store() function:
int d[10][20];
d[4][0] = 576;
can be replaced with
char d[200*sizeof(int)];
two_d_store(d, sizeof(int), 10, 20, 4, 0, 576);
So is there a simple way to implement this function without using arrays?
For any weird or not reason, if u dont want to have the standard way to access or set your memory structs, you could use
memcpy(void *dst, const void *src, size_t len);
Its a C function but it works 100% for C++ too.
Here are some general memory handling functions i found, good luck!:
void *memchr(const void *ptr, int ch, size_t len)
memchr finds the first occurence of ch in ptr and returns a pointer to it (or a null pointer if ch was not found in the first len bytes
int memcmp(const void *ptr1, const void *ptr2, size_t len)
memcmp is similar to strcmp, except that bytes equal to 0 are not treated as comparison terminators.
void *memcpy(void *dst, const void *src, size_t len)
memcpy copies len characters from src to dst and returns the original value of dst
The result of memcpy is undefined if src and dst point to overlapping areas of memory
void *memmove(void *dst, const void *src, size_t len)
memmove is just like memcpy except that memmove is guaranteed to work even if the memory areas overlap
void *memset(void *ptr, int byteval, size_t len)
memset sets the first len bytes of the memory area pointed to by ptr to the value specified by byteval
I changed the last argument to a pointer, not value, bcs we don't know what type it is. The max_y param is not needed. First i compute on n_array_ptr the adress of cell we want to change, and then memcpy the size_of_type bytes from new_value pointer to n_array_ptr. This function can be used for arrays of all types, bcs we are casting it void* and calculating the adress of block where our cell starts, and copy'ing exectly size_of_type bytes.
#include <iostream>
#include <cstring>
using namespace std;
void two_d_store(void * array_ptr, size_t size_of_type, int max_y, int max_x, int y, int x, void* new_value) {
void * n_array_ptr = array_ptr + size_of_type * (y * max_x + x);
memcpy(n_array_ptr, new_value, size_of_type);
}
int main() {
int d[10*20];
int new_val = 576;
two_d_store(d, sizeof(int), 10, 20, 4, 0, &new_val);
cout<<d[4*20]; //[4][20]
return 0;
}
void Manager::byteArrayToDoubleArray(byte ch[]) {
int counter = 0;
// temp array to break the byte array into size of 8 and read it
byte temp[64];
// double result values
double res[8];
int index = 0;
int size = (sizeof(ch) / sizeof(*ch));
for (int i = 0; i < size; i++) {
counter++;
temp[i] = ch[i];
if (counter % 8 == 0) {
res[index] = *reinterpret_cast<double * const>(temp);
index++;
counter = 0;
}
}
}
Here result would be a list of double values with count = 8.
Your problem is two things. You have some typos and misunderstanding. And the C++ standard is somewhat broken in this area.
I'll try to fix both.
First, a helper function called laundry_pods. It takes raw memory and "launders" it into an array of a type of your choice, so long as you pick a pod type:
template<class T, std::size_t N>
T* laundry_pods( void* ptr ) {
static_assert( std::is_pod<std::remove_cv_t<T>>{} );
char optimized_away[sizeof(T)*N];
std::memcpy( optimized_away, ptr , sizeof(T)*N );
T* r = ::new( ptr ) T[N];
assert( r == ptr );
std::memcpy( r, optimized_away, sizeof(T)*N );
return r;
}
now simply do
void Manager::byteArrayToDoubleArray(byte ch[]) {
double* pdouble = laundry_pods<double, 8>(ch);
}
and pdouble is a pointer to memory of ch interpreted as an array of 8 doubles. (It is not a copy of it, it interprets those bytes in-place).
While laundry_pods appears to copy the bytes around, both g++ and clang optimize it down into a binary noop. The seeming copying of bytes around is a way to get around aliasing restrictions and object lifetime rules in the C++ standard.
It relies on arrays of pod not having extra bookkeeping overhead (which C++ implementations are free to do; none do that I know of. That is what the non-static assert double-checks), but it returns a pointer to a real honest to goodness array of double. If you want to avoid that assumption, you could instead create each doulbe as a separate object. However, then they aren't an array, and pointer arithmetic over non-arrays is fraught as far as the standard is concerned.
The use of the term "launder" has to do with getting around aliasing and object lifetime requirements. The function does nothing at runtime, but in the C++ abstract machine it takes the memory and converts it into binary identical memory that is now a bunch of doubles.
The trick of doing this kind of "conversion" is to always cast the double* to a char* (or unsigned char or std::byte). Never the other way round.
You should be able to do something like this:
void byteArrayToDoubleArray(byte* in, std::size_t n, double* out)
{
for(auto out_bytes = (byte*) out; n--;)
*out_bytes++ = *in++;
}
// ...
byte ch[64];
// .. fill ch with double data somehow
double res[8];
byteArrayToDoubleArray(ch, 64, res);
Assuming that type byte is an alias of char or unsigned char or std::byte.
I am not completly sure what you are trying to achieve here because of the code (sizeof(ch) / sizeof(*ch)) which does not make sense for an array of undefined size.
If you have a byte-Array (POD data type; something like a typedef char byte;) then this most simple solution would be a reinterpret_cast:
double *result = reinterpret_cast<double*>(ch);
This allows you to use result[0]..result[7] as long as ch[] is valid and contains at least 64 bytes. Be aware that this construct does not generate code. It tells the compiler that result[0] corresponds to ch[0..7] and so on. An access to result[] will result in an access to ch[].
But you have to know the number of elements in ch[] to calculate the number of valid double elements in result.
If you need a copy (because - for example - the ch[] is a temporary array) you could use
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpret_cast<double*>(ch) + itemsInCh * sizeof(*ch) / sizeof(double));
So if ch[] is an array with 64 items and a byte is really an 8-bit value, then
std::vector<double> result(reinterpret_cast<double*>(ch), reinterpet_cast<double*>(ch) + 8);
will provide a std::vector containing 8 double values.
There is another possible method using a union:
union ByteToDouble
{
byte b[64];
double d[8];
} byteToDouble;
the 8 double values will occupie the same memory as the 64 byte values. So you can write the byte values to byteToDouble.b[] and read the resultingdouble values from byteToDouble.d[].
I have a struct SInfoEntry to store data that I read from a VCF file.
struct SInfoEntry
{
int type; //Info Type
std::string key; //Info Tag
void* values = NULL; //Data
int n; //Len
};
In the code below, I am trying to store my data in values variable in my struct. However I am getting error when I am trying to do that:
SInfoEntry infoEntry;
//This line is giving me EXC_BAD_ACCESS exception
bcf_get_info_values(m_pHeader, m_pRecord, "AF", (void**)(&infoEntry.values), &infoEntry.n, BCF_HT_REAL);
However instead if I declare a local array, the function successfully return me the data I want:
void* values = NULL;
int nvalue;
bcf_get_info_values(m_pHeader, m_pRecord, "AF", (void**)(&values), &nvalue, BCF_HT_REAL);
Why is that trying to read data into struct fails? Am I missing something in pointer arithmetic?
I am using 'bcf_get_info_values' function from an external library and here is the signature of the function:
int bcf_get_info_values(const bcf_hdr_t *hdr, bcf1_t *line, const char *tag, void **dst, int *ndst, int type);
Edit: Here is the Link of the source of bcf_get_info_values function. As I can see, I do not need to allocate memory since the function is using realloc().
What you are actually doing is coping data to an unallocated memory space.
In the first example it is probably initialized to NULL, hence the app crashed.
the second example is just coping data to random memory places, this shouldnt work and is extremely dangerous.
you can do one of the following:
Declare an array with size as the maximum object size you want to put in it:
uint8_t values[1000];
int nvalue;
bcf_get_info_values(m_pHeader, m_pRecord, "AF", (void**)(&values), &nvalue, BCF_HT_REAL);
Or allocate the array dynamically:
void* values = malloc(size);
int nvalue;
bcf_get_info_values(m_pHeader, m_pRecord, "AF", (void**)(&values), &nvalue, BCF_HT_REAL);
I have a question about void*. I have a function which captures blocks of 0.2 sec of audio by microphone. I have to process these blocks, in concrete a convolution.
This function returns these blocks of audio as a void * . To process this information I can't use void * because I can't access to them, so I have to convert in other kind of data, for example double but I don't know which length is assigned to this new pointer or how can I do it.
My code:
void Pre_proc_mono::PreProcess(void *data, int lenbytes, float t_max){
double * aux = (double*) data;
}
Now, aux's length is lenbytes too? Or I have to do something like:
int size = lenbytes/sizeof(double);
How can I make this work?
A pointer is an address in memory. This is the address of the first byte of data. The type of the pointer tells you how long is the data. So if we have
int *p
the value of p tells you where the data starts, and the type of the pointer, in this case int * tells you that from that address you need to take 4 bytes (on most architectures).
A void * pointer has only the starting address, but not the length of the data, so that's why you can't dereference a void * pointer.
sizeof(p) where p is a pointer (of any type) is the size of the pointer, and has nothing to do with the kind of data you find where the pointer points to
for instance:
sizeof(char) == 1
sizeof(char *) == 4
sizeof(void *) == 4
In your function:
void *data, int lenbytes, float t_max
data is a pointer to where the data starts, lenbytes is how many bytes the data has.
So you can have something like:
uint8_t *aux = (uint8_t*) data;
and you have a vector of lenbytes elements of type uint8_t (uint8_t is guaranteed to have 1 byte).
Or something like this:
double * aux = (double*) data;
and you have a vector of lenbutes/sizeof(double) elements of type double. But you need to be careful so that lenbytes is a multiple of sizeof(double).
Edit
And as regarding to what you should convert to, the answer depends on only the format of your blocks of data. Read the documentation, or search for an example.
I've got a byte array containing 8 bytes and would like to convert and use them as a double precision binary floating-point number.
Could someone please tell me how to convert it?
Try this:
double a;
memcpy(&a, ptr, sizeof(double));
where ptr is the pointer to your byte array. If you want to avoid copying use a union, e.g.
union {
double d;
char bytes[sizeof(double)];
} u;
// Store your data in u.bytes
// Use floating point number from u.d
Here is one solution using memcpy function:
double d = 0;
unsigned char buf[sizeof d] = {0};
memcpy(&d, buf, sizeof d);
Note that a solution like:
d = *((double *) buf);
shoud be avoided. This is undefined behavior because it potentially violates alignment and aliasing rules.
In C++:
double x;
char buf[sizeof(double)]; // your data
#include <algorithm>
// ...
std::copy(buf, buf + sizeof(double), reinterpret_cast<char*>(&x));
In C:
#include <string.h>
/* ... */
memcpy(&x, buf, sizeof(double));
In C++11, you can also use std::begin(buf) and std::end(buf) as the boundaries (include the header <iterator>), and in both languages you can use sizeof(buf) / sizeof(buf[0]) (or simply sizeof(buf)) for the size, all provided buf is actually an array and not just a pointer.