I want to copy a float buffer into a char (byte) buffer without allocating memory for two separate buffers. In another words I want to use one buffer and copy in place.
The Problem is that if I need a float buffer then in order to copy that to a char then I will need a char* pointer; If I were copying from float* to float* it would be easy as I would just pass in the same pointer for the target and the source.
eg.
void CopyInPlace(float* tar, float* src, int len) {
....
}
CopyInPlace(someBuffer, someBuffer, 2048);
void PackFloatToChar(char* tar, float* src, int len) {
}
????????
How would I do this?
Does memcpy copy in place?, if passed in the same pointer?
If you want to convert a float pointer to a char pointer, a cast is sufficient.
float* someBuffer;
...
char* someBuffer2 = (char*)someBuffer;
Your question seems a bit confused.
Do you want to simply interpret an array of floats as a char array (for something like writing to a file?). If so, simply cast. All pointers in C can be represented by char*'s.
memcpy will copy from one memory location to another. But keep careful track of whether your "len" parameter is the number of floats or number of bytes. If "len" is the count of floats in the array, multiply it by sizeof(float) in the memcpy call.
As an alternative to the casting that's already been recommended, you might want to consider using a union, something like:
union x {
float float_val;
char bytes[sizeof(float)];
};
There isn't likely to be a huge difference either way, but you may find one more convenient or readable than the other.
Related
I am learning C language and doing a lot of practice. I understand that * and ** are pointers in .c function.
Please consider the following function (another .c function)
void pcc(int* n, int* d, int* family, int* type, double* par, double* nu, double* out)
{
int i, j, in=1, k, **fam;
double *w, **v, t, **theta, **x, **ny;
…some works
}
My question is, why do we use the pointer in the argument of the function? Because as I understand we use the pointer to point the previous identifed elements.
Also, why do we use pointer for some elements that are not already defined in the arguments of the function. For example, in the last function we define a new element after writing the argument of the function:
int i, j, in=1, k, **fam;
double *w, **v, t, **theta, **x, **ny;
For instance, double *w was not in the argument of the function! also **v and other elements. How do we know they must get ** or *.
Any help please?
The reasons for declaring a variable a * or ** are countless, it's better to try and get a grip of what they actually mean instead of getting hung up on why they're used in this specific instance.
A pointer * is a reference to a memory location where a value is stored. In the case of a char it is a reference to a single memorylocation holding a byte, and in the case of an int it's usually 4 bytes on a 32bit system.
You can pass a pointer as an argument to indicate this is where you want the result to be stored. Another reason might be efficiency. If you have a very large struct it's better to pass a 4byte (on a 32bit system) reference to the area of memory where the struct lies instead of loading the entire struct on the stack.
A ** is a double pointer. It is pointing to a specific memory location that itself is storing the memory location of something else.
char a[5];
Here, the variable a is actually a char * pointing at the first element of a[], namely a[0].
char a[5][5];
Here a is a char **, pointing to the first element of a[][], namely a[0], which will return a char * pointing at a[0][0].
The second example is better when you want to fiddle with the pointers. Maybe you have a char** (an 'Array of strings'), and you want to replace one of the 'strings' (a string is just a char[] in c), you simply change the char* pointed to by the char**).
I hope this makes it a little clearer for you.
Pointers are used when we want the location of a value, as opposed to just the value. Now why would we want this? One simple scenario is actually illustrated in your question. In c, it is often inconvenient (if not impossible) to return more than one value from a function. An easy way to get around that is with pointers! When you pass arguments into a function normally, for example
int myFunction(int some_parameter);
you are actually passing a copy of some_parameter into your function. When the function returns, the original value of some_parameter is unchanged. But what if we want to change some_parameter in the function? We pass a pointer to the value instead. This allows us to directly change the value of some_parameter at its original memory location, instead of a copy. So as you can see, if we instead had
void myFunction(int* parameter1, int* parameter2) {
*parameter1 = 1;
*parameter2 = 2;
}
When you exit the function, your values parameter1 and parameter 2 will be 1 and 2 respectively, even though you never actually returned a value!
Pointers are one of the most useful and difficult parts about c, and I recommend you consult the other sources that others have selected in order to learn more about them.
In C you traditionally use pointers to modify variables that were declared at a different scope than the one of your function.
Pointers to pointers (**) though, are usually used when you want to manipulate those addresses in some way.
Now as for you question:
How do we know they must get ** or *?
Well it depends on what you want to do with the data. If you want to manipulate the value you only need a pointer; if you want to manipulate the address you may need a pointer to a pointer.
I am currently writing a terminal based hex editor. and I have a few question regarding memory allocation.
To track changes the user has made I write them to an array of arrays like so, the [i][0] is the absolute offset of the change from the beginning of the file and [i][1] is the change itself:
unsigned long long writebuffer[10000][2];
but I have 2 problems with this. the first array (writebuffer[i][0]) NEEDS to be the sizeof unsigned long long but the second one ([i][1]) can be as small as sizeof unsigned char. Is it possible to do something like this??
also can I dynamically allocate the first index of writebuffer so I wouldn't initialize it like above but more like:
unsigned long long **writebuffer;
and then change the first index with malloc() and realloc(); while the second index would be 2 but have the size of a unsigned char.
Why not use a struct?
typedef struct {
long long offset;
int change; /* or unsigned short, or whatever you feel is right */
} t_change;
Be aware that the struct will likely get padded by the compiler to a different size if you choose to use unsigned char for the change element. What it gets padded to depends on your compiler, the compiler settings, and the target architecture.
You may define an array of type void:
void **writebuffer;
and then allocate and use each element as you like, for example:
*writebuffer[0] = (char*)malloc(sizeof(char));
I have a lot of functions that expect a string as argument, for which I use char*, but all my functions that expect a byte-array, also use char*.
The problem is that I can easily make the mistake of passing a byte-array in a string-function, causing all kinds of overflows, because the null-terminator cannot be found.
How is this usually delt with? I can imagine changing all my byte-array functions to take an uint8_t, and then the compiler will warn about signed-ness when I pass a string. Or what is the right approach here?
I generally make an array something like the following
typedef struct {
unsigned char* data;
unsigned long length;
unsigned long max_length;
} array_t;
then pass array_t* around
and create array functions that take array_t*
void array_create( array_t* a, unsgined long length) // allocates memory, sets the max_length, zero length
void array_add(array_t* a, unsigned char byte) // add a byte
etc
The problem is more general in C than you are thinking. Since char* and char[] are equivalent for function parameters, such a parameter may refer to three different semantic concepts:
a pointer on one char object (this is the "official" definition of pointer types)
a char array
a string
In most cases where is is possible the mondern interfaces in the C standard uses void* for an untyped byte array, and you should probably adhere to that convention, and use char* only for strings.
char[] by themselves probably are rarely used as such; I can't imagine a lot of use cases for these. If you think of them as numbers you should use the signed or unsigned variant, if you see them just as bit pattern unsigned char should be your choice.
If you really mean an array as function parameter (char or not) you can mark that fact for the casual reader of your code by clearly indicating it:
void toto(size_t n, char A[const n]);
This is equivalent to
void toto(size_t n, char *const A);
but makes your intention clearer. And in the future there might even be tools that do the bounds checking for you.
Write a common structure to handle both string and bytes.
struct str_or_byte
{
int type;
union
{
char *buf;
char *str;
}pointer;
int buf_length;
}
If type is not string then access the pointer.buf only upto buf_length. Otherwise directly access pointer.str without checking buf_length and maintain it as null terminated string.
Or else maintain string also as byte array by considering only length, dont keep null terminated charater for string.
struct str_or_byte
{
char *buf;
int buf_length;
}
And dont use string manuplation functions which are not considering length. That means use strncpy, strncat, strncmp ... instead of strcpy, strcat, strcmp...
C using convention. Here's the rules I use (fashioned after the std lib)
void foo(char* a_string);
void bar(void* a_byte_array, size_t number_of_bytes_in_the_array);
This is easy to remember. If you are passing a single char* ptr, then it MUST be a null-terminated char array.
Suppose I allocate some memory.
char* buffer = (char*)my_malloc(2062);
I assign char values to the first 14 bytes from a previously defined array named header.
memcpy(buffer, header, 14);
Then I want to treat the rest of the allocated space as pointers to float.
float* float_buffer = (float*)(buffer + 14);
some_function(float_buffer);
Then at some point later on I need to send all the data out.
transmit(buffer);
my_free(buffer);
Is this correct way to treat memory? Is the float* cast ok? I am having issues where I am losing values and not getting the correct results.
My question is:
If you have to treat allocated memory as different types but then send it as char* at the end of the processing.....is this the correct way to do it?
I checked the ptr values and they are the same when they are float* and char* but I am not getting the correct result.
One of my restrictions is that I can only initially allocate one block of memory from a static buffer. So calling another malloc as a different type (float*) is not allowed.
To make this work (portably, at least), you would have to ensure (at a minimum) that the float_buffer was sizeof(float)-aligned. You could do this by allocating sizeof(float) - 1 extra bytes, observing the result of the malloc call modulo sizeof(float), and ignoring the first few bytes as appropriate. (You would, of course, have to keep the original pointer around in order to make the free() call.)
You probably don't want to do this, though. It sounds like the purpose of the 'buffer' is to accumulate data to be sent over a network or something like that, and that the floats are going to be copied in from somewhere else. What you should really do is cast the other way around: treat the buffer as a char[] always, and reinterpret the source floats as a sequence of chars when you copy them over. That is
char* buffer = malloc(total_size);
char* float_start = buffer + header_size;
memcpy(float_start, (char*)float_source, sizeof(float) * float_count);
transmit(buffer, total_size);
free(buffer);
Conceptually, this is OK - but you have to do some additional work to ensure it will work reliably.
A potential problem is that you cannot just access any arbitrary address as a float. There may be specific alignment requirements - the address returned by malloc() is required to be correctly aligned for access as any type, but once you add 14 to that address, all bets are off (except for char).
To ensure the correct alignment, you must ensure that the address you add to buffer is a multiple of sizeof(float). You can do that by adding padding using the following formula:
#define PAD_OFFSET(offset, type) ((offset) + sizeof(type) - 1) & ~(sizeof(type) - 1))
float *float_buffer = (float *)(buffer + PAD_OFFSET(14, float));
Note that this will create a gap - padding - between your chars and your floats.
Alternatively, you can define a struct, and the compiler will figure the padding out for you. This uses a C99 feature called a flexible array member:
struct foo {
char abc[14];
float xyz[];
};
struct foo *buffer = malloc(2062);
memcpy(&buffer->abc, header, 14);
some_function(&buffer->xyz);
transmit(buffer); /* Presuming transmit() expects a void * parameter. */
If you wish to do it without padding, you cannot directly access the memory in buffer as floats - you will have to create a temporary array and copy it in:
float temp[500]; /* Or whatever size */
some_function(&temp);
memcpy(buffer + 14, temp, sizeof temp);
I am speculating here, but since the prototype for malloc is
void *malloc(size_t size);
you are essentially casting the buffer of type void* to char*, so later casting another chunk of the buffer to float* would be fine, so long as you take care of the pointer accounting properly.
I have a structure that has an array of pointers. I would like to insert into the array digits in string format, i.e. "1", "2", etc..
However, is there any difference in using either sprintf or strncpy?
Any big mistakes with my code? I know I have to call free, I will do that in another part of my code.
Many thanks for any advice!
struct port_t
{
char *collect_digits[100];
}ports[20];
/** store all the string digits in the array for the port number specified */
static void g_store_digit(char *digit, unsigned int port)
{
static int marker = 0;
/* allocate memory */
ports[port].collect_digits[marker] = (char*) malloc(sizeof(digit)); /* sizeof includes 0 terminator */
// sprintf(ports[port].collect_digits[marker++], "%s", digit);
strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker]));
}
Yes, your code has a few issues.
In C, don't cast the return value of malloc(). It's not needed, and can hide errors.
You're allocating space based on the size of a pointer, not the size of what you want to store.
The same for the copying.
It is unclear what the static marker does, and if the logic around it really is correct. Is port the slot that is going to be changed, or is it controlled by a static variable?
Do you want to store only single digits per slot in the array, or multiple-digit numbers?
Here's how that function could look, given the declaration:
/* Initialize the given port position to hold the given number, as a decimal string. */
static void g_store_digit(struct port_t *ports, unsigned int port, unsigned int number)
{
char tmp[32];
snprintf(tmp, sizeof tmp, "%u", number);
ports[port].collect_digits = strdup(tmp);
}
strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker]));
This is incorrect.
You have allocated onto collect_digits a certain amount of memory.
You copy char *digits into that memory.
The length you should copy is strlen(digits). What you're actually copying is sizeof(ports[port].collect_digits[marker]), which will give you the length of a single char *.
You cannot use sizeof() to find the length of allocated memory. Furthermore, unless you know a priori that digits is the same length as the memory you've allocated, even if sizeof() did tell you the length of allocated memory, you would be copying the wrong number of bytes (too many; you only need to copy the length of digits).
Also, even if the two lengths are always the same, obtaining the length is this way is not expressive; it misleads the reader.
Note also that strncpy() will pad with trailing NULLs if the specified copy length is greater than the length of the source string. As such, if digits is the length of the memory allocated, you will have a non-terminated string.
The sprintf() line is functionally correct, but for what you're doing, strcpy() (as opposed to strncpy()) is, from what I can see and know of the code, the correct choice.
I have to say, I don't know what you're trying to do, but the code feels very awkward.
The first thing: why have an array of pointers? Do you expect multiple strings for a port object? You probably only need a plain array or a pointer (since you are malloc-ing later on).
struct port_t
{
char *collect_digits;
}ports[20];
You need to pass the address of the string, otherwise, the malloc acts on a local copy and you never get back what you paid for.
static void g_store_digit(char **digit, unsigned int port);
Finally, the sizeof applies in a pointer context and doesn't give you the correct size.
Instead of using malloc() and strncpy(), just use strdup() - it allocates the buffer bin enough to hold the content and copies the content to the new string, all in one shot.
So you don't need g_store_digit() at all - just use strdup(), and maintain marker on the caller's level.
Another problem with the original code: The statement
strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker]));
references marker and marker++ in the same expression. The order of evaluation for the ++ is undefined in this case -- the second reference to marker may be evaluated either before or after the increment is performed.