Declaring array of voids - c

I'm writing a program that copies files. I've used a buffer in order to store the information that the read() function provides and then give this data to the write() function. I've used this declaration:
static void buffer[BUFFER_SIZE];
The problem is that I get the the error error: declaration of ‘buffer’ as array of voids.
I don't understand why declaring an array of void is an error. How can I declare a block of memory without a specific type?

I don't understand why declaring an array of void is an error.
The technical reason you cannot declare an array-of-void is that void is an incomplete type that cannot be completed. The size of array elements must be known but the void type has no size. Note that you are similarly unable to declare a void object, as in
void foo;
Note that a pointer-to-void has a specific size, which is why
void *foo;
is valid, as well as sizeof(foo), but sizeof(*foo) would be invalid.
How can I declare a block of memory without a specific type?
For generic memory buffers, use an array of plain char or unsigned char (or even uint8_t). I usually prefer plain char when I need to pass pointers to the str* family of functions where array of unsigned char would lead to diagnostics about incompatible pointers.

Use an array of char or unsigned char instead.

When declaring an array, the compiler must know the size of the array.
The void type has no size. So compiler report error.

This is how you do it, although it is not an array of voids as you may have wanted, it is an array of void pointers; in each cell of this void pointer you can assign ANYTHING.
If you wish to store a variable, you simply cast it to (void*), here is an example:
void *XPoint[5] = { 0 };
XPoint[0] = (void*)5; // int
XPoint[1] = "Olololo!"; // char*
XPoint[2] = (void*)'x'; // char
XPoint[3] = (void*)structA.nNum; // struct int

You also can declare void pointer:
void* buffer;
// just pointers for simple work with allocated piece of memory
char* chBuf;
long* intBuf;
then use malloc() for this pointer and work with this piece of memory like with an any array (char, short, long, float, double or your own type). Don't forget to use free() to avoid memory leak in this case.
buffer = malloc (BUFFER_SIZE);
if (buffer==NULL)
exit (1);
// init our buffers
chBuf=(*char)buffer;
intBuf=(*long)buffer;

Related

What does int * and double ** mean for elements outside the C function's arguments?

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.

Generic function for malloc to accept all data type

Given a function as(it can use malloc() internally)as void* function_ptr(void *ptr, int size);
where void *ptr is a void pointer and size is the number and in return it should allocate the memory depending on the data type. For int, it should allocate 4*size(considering 32 bit) and for char 1*size.
for example,
for integer data type, function_ptr((void *)some_int_ptr, 10 )
it should allocate 10 *4(32 bit) = 40 bytes and
function_ptr((void *)some_char_ptr, 10 ), 10 bytes should be allocated
Question is how can we typecast void * to int/char/double pointer as function does not know as which datatype was typecast to void* ?
It was a interview question, i tried answering as sending 1 more parameter which mentions the data type and hence we can allocate and assign memory but was not accepted as
void* function_ptr(void *ptr, int size, int data_type);
You can't know the data type from inside the function, as there is no type information available. There are two options:
1) Either make the function work on the size in bytes, then it doesn't need to know the type. Perhaps this was actually what the interviewer meant?
2) Rewrite the function so that it includes type information somewhere.
There are also bad alternatives such as using global variables or replacing the function with a wrapper macro, but neither is recommended.

Is it valid to call malloc with a pointer of the type of the first member?

I am building a hash library, this library works with different structs and all those structs haves an unsigned type as first member, an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct data {
unsigned hash;
void (*func)(struct data *);
};
struct another_data {unsigned hash; int value;};
static void *hash_insert(const char *text, size_t size)
{
unsigned *hash;
hash = malloc(size);
// *hash = hash(text);
*hash = (unsigned)strlen(text);
return hash;
}
static void func(struct data *data)
{
printf("%u\n", data->hash);
}
int main(void)
{
struct data *data;
data = hash_insert("Some text", sizeof *data);
data->func = func;
data->func(data);
free(data);
return 0;
}
Since the first member of the struct and the struct itself haves the same alignment requirements, is it valid to call malloc with a pointer of the type of the first member in order to reserve space for the entire struct?
unsigned *hash = malloc(size); /* where size is the size of the struct */
EDIT:
In this related question provided by #MohitJain:
struct Msg
{
unsigned int a;
unsigned int b;
};
...
uint32_t* buff = malloc(sizeof(Msg));
// Alias that buffer through message
Msg* msg = (Msg*)(buff);
The strict aliasing rule makes this setup illegal
But in my case I am returning a void * from the function, I can use this (returned) pointer inside main without alignment issues, is this assumption correct?
The rules about effective type and pointer aliasing say that it is fine to convert pointers between a struct (or any other "aggregate") and a pointer of the same type as the first appearing member in the struct. And another rule says that structs are not allowed to have padding in the very beginning.
So it is fine as far as the C standard goes... which doesn't really say much of the quality of the program.
The code does not make much sense. You clearly want to use the whole struct, so why not return a pointer of the struct type? Don't complicate things for the sake of it. You should always avoid using void* when there is no need for it, to increase type safety.
Overall, all these things would sort themselves out in a multi-file project with proper program design. If you had a separate file with the hash type and all functions using that type, there would be no doubt of how to write the program.
malloc is guaranteed to return memory aligned for any type.
Therefore it will work regardless of the alignment requirement of the different subtypes.
Since structure member are allocated in the order they are declared, using
unsigned *hash = malloc(size); /* where size is the size of the struct */
can work if your pourpose is just using the hash data.
It fails if you want to apply pointer aritmetic on it, so in this case using
hash++
is an undefined behavior.
Yes it is perfectly fine for first member type to point to the memory returned by malloc (Memory is aligned for any data type). What you do with this memory later may cause issues if you are not careful.
[Extracts from Joachim Pileborg's answer # Maintaining an array of pointers in C that points to two related types with minor changes]
Having a structure inside other structures or a common data type in other structures is a common way of emulating inheritance in C. This common member should contain the minimal set of data common to all structures in the "inheritance" hierarchy, and it must always be the first member in the inheriting structures.
Possible issue with this scheme is:
This "inheritance" scheme will work on all modern PC-like systems and their compilers, and have done so for a long time, but there's no guarantee that it will work on all systems and all compilers (if you're planning on porting the code to some rare system with weird hardware and compiler you might want to look out, but the cases where the "inheritance" scheme will not work is very small, and most people will never come in contact with such a system in their entire lifetime.) But once you point the same memory with struct data *, you may fall victime of strict aliasing rule. So you need to be careful there. Further readL What is the strict aliasing rule?
unsigned *hash = malloc(size);
This will create allocate an array of unsigned integers. Total number of integers allocated will be size/sizeof(int). hash here is pointer to int.
Since the first member of the struct and the struct itself haves the same alignment requirements, is it valid to call malloc with a pointer of the type of the first member in order to reserve space for the entire struct?
The point is, that hash here is a separate variable which has nothing to do with the hash inside the structure. (It is in a separate namespace, if you want to look it up)
You can then cast hash to the struct variable.
struct data *data;
unsigned *hash = malloc(size * sizeof(struct));
data = (struct data *) hash;
But, what is the point. You can just as well remove the unnecessary unsigned hash pointer and go with the traditional.
struct data *data;
data = malloc(size * sizeof(struct));

Distinguish between string and byte array?

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.

Store pointer address in malloced memory

This feels like a silly question, but I just can't work out a clean solution and can't find a similar question in the mass of other pointer related questions.
I have some dynamically allocated memory of unknown type and want to store a pointer inside it at the start. Dynamic memory returned by malloc should be suitably aligned so I don't think I have to worry about alignment when writing to the start of the allocated block.
This is my code, which works, but I'm representing a pointer as a 64-bit integer and want to do it in a more clean/portable way:
void *my_area = malloc(512);
void *my_pointer = get_my_pointer();
((long long *) my_area)[0] = (long long) my_pointer;
The cast to long long is just extra baggage. Cast to void * instead.
void *my_area = malloc(512);
void *my_pointer = get_my_pointer();
((void **) my_area)[0] = my_pointer;
(I assume that this is for some kind of freelist or the like, i.e., you don't need to use the structure at the same time.)
What will be found in my_area[0] is pointer to something, right ?
Then you can allocate my_area to be of type void **, which represent a pointer to a pointer containing memory area.
void **my_area = malloc(512 * sizeof(*my_area)); // alloc 512 pointer sized memory blocks
void *my_pointer = get_my_pointer();
my_area[0] = my_pointer;
Define a struct with internal array of 8 bytes. Replace all the long long type references with your custom struct. This way you will not depend on platform-specific size of long long. The struct will be 64 bits on all platforms(you can add #pragma pack if you worry about alignment )

Resources