Deferencing Void Pointer / Void Pointer Copy - c

Platform: Linux 3.2.0 x86 (Debian Wheezy)
Compiler: GCC 4.7.2 (Debian 4.7.2-5)
I am writing a function that copies the contents of a buffer to another buffer. I use a void pointer so that the function is not type specific. I have a testable version and it appears that the function is working properly. But I do not know if what I am doing is legal so my question is what are the pitfalls of what I have done if there are any.
#include <stdio.h>
#include <stdlib.h>
void* voidcpy(void *void_ptr, size_t nbytes)
{
char *char_ptr = void_ptr;
char *cpy_char_ptr = NULL;
size_t i = 0;
if((cpy_char_ptr = malloc(nbytes)) == NULL) return NULL;
for(; i < nbytes; i++) cpy_char_ptr[i] = char_ptr[i];
return cpy_char_ptr;
}
int main()
{
short int *intp = NULL;
short int *cpy_intp = NULL;
size_t siz = 5;
int i = 0;
if((intp = malloc(siz * sizeof(short int))) == NULL)
{
perror("(malloc)");
return -1;
}
intp[0] = 0;
intp[1] = 14;
intp[2] = 187;
intp[3] = 12678;
intp[4] = -234;
if((cpy_intp = voidcpy(intp, siz * sizeof(short int))) == NULL)
return -2;
printf("intp = %p\ncpy_intp = %p\n\n", (void*)intp, (void*)cpy_intp);
for(; i < siz; i++) printf("cpy_intp = %i\n", cpy_intp[i]);
free(intp);
free(cpy_intp);
return 0;
}

Yes, this is perfectly legal, in C you can legally assign a void pointer to any other pointer type and you can assign any pointer type to a void pointer.
In C++ this is not allowed. In C++ you would have to use a reinterpret_cast to cast to a different pointer type because the free void pointer casting that is allowed in C is considered a "loop hole" that is easy to make mistakes with.
Of course there is a truth to that idea, if you're not careful you could be doing the wrong thing, e.g. you could easily pass a pointer to a pointer to this function by mistake and then your function will happily overwrite whatever is on the stack beyond that pointer. This is no fault of your implementation however, it's just the way the function is to be used and memcpy behaves no differently.
Nevertheless you would be better off using memcpy instead as this will very likely be much better optimized, though these days the compiler will probably make a pretty decent version out of your code as well.
A few more pointers;
1) you do not need to malloc the original array, you can initialize it statically like so
short int int_arr[] = {
0,
14,
187,
12678,
-234,
};
2) you can then call your function in the following way:
cpy_int_arr = voidcpy(int_arr, sizeof(int_arr));
3) if you don't want to define the array statically, then use the pointer to get the element size, that way you can change the array type without needing to change it somewhere else in the code, which reduces the potential dangers of the "loop hole" void casting:
cpy_intp = voidcpy(intp, siz * sizeof(*intp));
4) you don't need to cast to void* in the printf call
5) try to assign variables immediately and do not put assignments inside of if statements:
char *cpy_char_ptr = malloc(nbytes)
if (cpy_char_ptr == NULL)
return NULL;
6) similarly you can define a iteration variable inside the loop clause:
for(size_t i = 0; i < nbytes; i++) cpy_char_ptr[i] = char_ptr[i];
The reason to define variables as late as possible and initialize them immediately is that you keep the scope of the variables as small as possible and you can not mistakenly use a variable before it is initialized.
7) (personal preference) don't use type names in your identifiers (intp, voidcpy) your code will either become difficult to read/understand if your identifier states a type different from what the variable actually is, (e.g. your type is actually a short int and not an int as the variable name would suggest,) or you will need to change the identifier throughout the entire code whenever you change the type with the possibility of making mistakes.

Related

Warning: Return from incompatible pointer type

The code below is producing a compiler warning: return from incompatible pointer type. The type I'm returning seems to be the issue but I cant seem to fix this warning.
I have tried changing the type of hands to int *. Also have tried returning &hands.
int * dealDeck(int numPlayers, int numCards, int cardDeck[])
{
static int hands[MAX_PLAYERS][MAX_CARDS]={0};
int start = 0;
int end = numCards;
int player, hand, j;
int card;
for(player = 0; player < numPlayers; player++)
{
for(hand = start, j=0; hand < end; hand++,j++)
{
card = cardDeck[hand];
hands[player][j] = card;
}
start = end;
end += numCards;
}
return hands;
}
This function should return a pointer to the array "hands". This array is then passed to another function which will print out its elements.
The hands variable is not an int * this is a int **
So you need to return a int **
This is a 2d array.
First of all, you have declared return type of int *, which would mean, that you are trying to return an array, while you want to return a 2-dimensional array. The proper type for this would usually be int **, but that won't cut it here. You opted to go with static, fixed size array. That means, that you need to return pointer to some structures of size MAX_CARDS * sizeof(int) (and proper type, which is the real problem here). AFAIK, there is no way to specify that return type in C*.
There are many alternatives though. You could keep the static approach, if you specify only up to 1 size (static int *hands[MAX_PLAYERS] or static int **hands), but then you need to dynamically allocate the inner arrays.
The sane way to do it is usually "call by reference", where you define the array normally before calling the function and you pass it as a parameter to the function. The function then directly modifies the outside variables. While it will help massively, with the maintainability of your code, I was surprised to find out, that it doesn't get rid of the warning. That means, that the best solution is probably to dynamically allocate the array, before calling the function and then pass it as an argument to the function, so it can access it. This also solves the question of whether the array needs to be initialized, and whether = {0} is well readable way to do it (for multidimensional array) , since you'll have to initialize it "manually".
Example:
#include <stdio.h>
#include <stdlib.h>
#define PLAYERS 10
#define DECKS 20
void foo(int **bar)
{
bar[0][0] = 777;
printf("%d", bar[0][0]);
/*
* no point in returning the array you were already given
* but for the purposes of curiosity you could change the type from
* void to int ** and "return bar;"
*/
}
int main()
{
int **arr;
arr = malloc(sizeof(int *) * PLAYERS);
for (size_t d = 0; d < DECKS; d++) {
/* calloc() here if you need the zero initialization */
arr[d] = malloc(sizeof(int) * DECKS);
}
foo(arr);
return 0;
}
*some compilers call such type like int (*)[20], but that isn't valid C syntax

How to return multiple types from a function in C?

I have a function in C which calculates the mean of an array. Within the same loop, I am creating an array of t values. My current function returns the mean value. How can I modify this to return the t array also?
/* function returning the mean of an array */
double getMean(int arr[], int size) {
int i;
printf("\n");
float mean;
double sum = 0;
float t[size];/* this is static allocation */
for (i = 0; i < size; ++i) {
sum += arr[i];
t[i] = 10.5*(i) / (128.0 - 1.0);
//printf("%f\n",t[i]);
}
mean = sum/size;
return mean;
}
Thoughts:
Do I need to define a struct within the function? Does this work for type scalar and type array? Is there a cleaner way of doing this?
You can return only 1 object in a C function. So, if you can't choose, you'll have to make a structure to return your 2 values, something like :
typedef struct X{
double mean;
double *newArray;
} X;
BUT, in your case, you'll also need to dynamically allocate the t by using malloc otherwise, the returned array will be lost in stack.
Another way, would be to let the caller allocate the new array, and pass it to you as a pointer, this way, you will still return only the mean, and fill the given array with your computed values.
The most common approach for something like this is letting the caller provide storage for the values you want to return. You could just make t another parameter to your function for that:
double getMean(double *t, const int *arr, size_t size) {
double sum = 0;
for (size_t i = 0; i < size; ++i) {
sum += arr[i];
t[i] = 10.5*(i) / (128.0 - 1.0);
}
return sum/size;
}
This snippet also improves on some other aspects:
Don't use float, especially not when you intend to return a double. float has very poor precision
Use size_t for object sizes. While int often works, size_t is guaranteed to hold any possible object size and is the safe choice
Don't mix output in functions calculating something (just a stylistic advice)
Declare variables close to where they are used first (another stylistic advice)
This is somewhat opinionated, but I changed your signature to make it explicit the function is passed pointers to arrays, not arrays. It's impossible to pass an array in C, therefore a parameter with an array type is automatically adjusted to the corresponding pointer type anyways.
As you don't intend to modify what arr points to, make it explicit by adding a const. This helps for example the compiler to catch errors if you accidentally attempt to modify this array.
You would call this code e.g. like this:
int numbers[] = {1, 2, 3, 4, 5};
double foo[5];
double mean = getMean(foo, numbers, 5);
instead of the magic number 5, you could write e.g. sizeof numbers / sizeof *numbers.
Another approach is to dynamically allocate the array with malloc() inside your function, but this requires the caller to free() it later. Which approach is more suitable depends on the rest of your program.
Following the advice suggested by #FelixPalmen is probably the best choice. But, if there is a maximum array size that can be expected, it is also possible to wrap arrays in a struct, without needing dynamic allocation. This allows code to create new structs without the need for deallocation.
A mean_array structure can be created in the get_mean() function, assigned the correct values, and returned to the calling function. The calling function only needs to provide a mean_array structure to receive the returned value.
#include <stdio.h>
#include <assert.h>
#define MAX_ARR 100
struct mean_array {
double mean;
double array[MAX_ARR];
size_t num_elems;
};
struct mean_array get_mean(int arr[], size_t arr_sz);
int main(void)
{
int my_arr[] = { 1, 2, 3, 4, 5 };
struct mean_array result = get_mean(my_arr, sizeof my_arr / sizeof *my_arr);
printf("mean: %f\n", result.mean);
for (size_t i = 0; i < result.num_elems; i++) {
printf("%8.5f", result.array[i]);
}
putchar('\n');
return 0;
}
struct mean_array get_mean(int arr[], size_t arr_sz)
{
assert(arr_sz <= MAX_ARR);
struct mean_array res = { .num_elems = arr_sz };
double sum = 0;
for (size_t i = 0; i < arr_sz; i++) {
sum += arr[i];
res.array[i] = 10.5 * i / (128.0 - 1.0);
}
res.mean = sum / arr_sz;
return res;
}
Program output:
mean: 3.000000
0.00000 0.08268 0.16535 0.24803 0.33071
In answer to a couple of questions asked by OP in the comments:
size_t is the correct type to use for array indices, since it is guaranteed to be able to hold any array index. You can often get away with int instead; be careful with this, though, since accessing, or even forming a pointer to, the location one before the first element of an array leads to undefined behavior. In general, array indices should be non-negative. Further, size_t may be a wider type than int in some implementations; size_t is guaranteed to hold any array index, but there is no such guarantee for int.
Concerning the for loop syntax used here, e.g., for (size_t i = 0; i < sz; i++) {}: here i is declared with loop scope. That is, the lifetime of i ends when the loop body is exited. This has been possible since C99. It is good practice to limit variable scopes when possible. I default to this so that I must actively choose to make loop variables available outside of loop bodies.
If the loop-scoped variables or size_t types are causing compilation errors, I suspect that you may be compiling in C89 mode. Both of these features were introduced in C99.If you are using gcc, older versions (for example, gcc 4.x, I believe) default to C89. You can compile with gcc -std=c99 or gcc -std=c11 to use a more recent language standard. I would recommend at least enabling warnings with: gcc -std=c99 -Wall -Wextra to catch many problems at compilation time. If you are working in Windows, you may also have similar difficulties. As I understand it, MSVC is C89 compliant, but has limited support for later C language standards.

Segfault when trying to index pointer to pointers in function

I'm trying to do something with an array (malloc-ed), namely arr of a custom struct. The array is passed by reference to a function. I get a segfault whenever I tried to index anything other than arr[0] in the function at runtime (e.g (*arr[1])->i = 3;). Why is this happening?
The full source code is:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
typedef struct{
int i;
float f;
}foo;
void doSomething(foo ***arr);
int main()
{
foo **arr = (foo**) malloc (SIZE * sizeof(foo*));
int i;
for(i = 0; i < SIZE; i++)
arr[i] = (foo*)malloc(sizeof(foo));
arr[1]->i = 1;
printf("Before %d\n",arr[1]->i );
doSomething(&arr);
printf("After %d\n",arr[1]->i );
return 0;
}
void doSomething(foo ***arr)
{
(*arr[1])->i = 3;
}
Your problem is the line
(*arr[1])->i = 3;
Because the subscripting operator's evaluation precedes the dereferencing's evaluation it is equivalent to the following:
(*(arr[1]))->i = 3;
This is obviously wrong. You need
(*arr)[1]->i = 3;
therefore.
Notes:
do not cast the result of malloc
add #include <stdlib.h> to resolve the warning
adding an extra level of indirection (foo*** pointing to foo**) is unnecessary; just copy by value
(in addition to the upper note) a good old 1D array should actually be sufficient in your case
call free after malloc
The warning you get is because you forgot to #include <stdlib.h>, so malloc is not declared, so the compiler assumes it should return int. This can lead to all kinds of fun problems. (And you should remove those casts.)
The other problem is in this line: (*arr[1])->i = 3;
Postfix operators (like []) bind tighter than prefix operators (like *), so *arr[1] parses as *(arr[1]).
You can write (*arr)[1]->i instead to fix this, but as it turns out, your function never actually modifies *arr, so there's no reason to pass arr (the other arr, the one in main)'s address to it. Just do this:
void doSomething(foo **arr)
{
arr[1]->i = 3;
}
and call it as doSomething(arr).

Initializing local pointers by passing the address of a pointer

I see the following way of initializing a local pointer in almost every part of my code. want to understand the reason and intricacies in doing so.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void initialize_p(char **p)
{
char *p_local = NULL;
p_local=malloc(6);
strcpy(p_local,"sandy");
*p = p_local;
}
int main(void)
{
char *p = NULL;
initialize_p(&p);
printf("Name : %s\n",p);
return 0;
}
It is just that, i am showing here with simple string. And in my actual code, it is being done using structures.
I kind of understand the above logic and also I don't. Please clear the concept involved in the above style of implementing. Also, let me know if there is any other better way of doing the same.
Please Enlighten .. :)
I'd probably return the newly allocated string instead of passing a pointer to a pointer as an argument:
char *initialize(void) {
char *init = "sandy";
char *ret = malloc(sizeof(init)+1);
if (ret != NULL)
strcpy(ret, init);
return ret;
}
int main() {
char *p = initialize();
printf("Name: %s\n", p);
free(p);
return 0;
}
In initialize_p a chunk of memory is allocated and some string is copied into the memory. In order for the caller of initializer to get the address of this new chunk of memory the address of the pointer p is passed to initialize_p:
char **p
+---+---+---+---+---+----+
*p -> | s | a | n | d | y | \0 |
+---+---+---+---+---+----+
if only the *p would have been passed then setting the pointer inside the function would be the equivalent of:
void foo(int a)
{
a=3;
...
}
a better way would be to use strdup which does the same thing as you do in your function
char* initialize_p()
{
return strdup("sandy");
}
also make sure you free the string that is returned to avoid memory leak.
I'd suggest you to create allocation and deallocation function pair
char *createP()
{
char *p = NULL;
p=malloc(6);
strcpy(p,"sandy");
return p;
}
void freeP(char *p)
{
if (p) free(p);
}
int main(void)
{
char *p = createP();
printf("Name : %s\n",p);
freeP(p);
return 0;
}
Clearing the concept? Well, in such a simple case I don't see the point in operating with byref output parameters - for me, object-oriented-like structure constructor functions are easier to understand if they work like this:
struct foo *bar = myobj_new(); // uses malloc and returns a pointer
// do something with bar
myobj_destroy(bar); // uses free
Some agree that this design is good because then the return value of the function can be used as an error/success code (have you seen SQLite3?), but I disagree. I think the primary, the most important result of a function should go through the return value, and not some auxiliary stuff. (I tend to write libraries in which failure is indicated by returning NULL and setting a byref-passed error code).
The only valid scenario I can think of is when it's more logical or symmetrical to pass arguments like this. For example, imagining a very strange sort function which is similar to the C stdlib function qsort(), but requires its comparison function itself to make the swapping of two elements when needed. The comparison function obviously needs byref access to its two parameters in order to exchange them, but it may also be useful to return the originally encountered order to the caller sort function in order to optimize the algorithm. So this comparison function could be something like:
int compare(void *a, void *b)
{
int x = *(int *)a;
int y = *(int *)b;
if (x > y)
{
*(int *)a = y;
*(int *)b = x;
return +1;
} else if (x < x) {
return -1;
}
return 0;
}
Well, pretty much that's it about my opinion...
it's an out-parameter. the function produces a result for you, and saves it to the parameter you pass. this is often used when the size of the result may vary, or if the type of the parameter is Opaque.
Personally, I think returning the result is much clearer, and is less error-prone when a dynamic allocation is required (as seen in JerryCoffin's answer +1).
when a dynamic allocation is not required, then pass it by reference (as a non-const parameter) if it is not trivially small:
struct t_struct { int a[100]; };
void InitStruct(struct t_struct* pStruct) {
pStruct->a[0] = 11;
...
}
struct t_struct s;
void InitStruct(&s);
and if it is trivially small, you may consider returning by value.

Passing pointers of arrays in C

So I have some code that looks like this:
int a[10];
a = arrayGen(a,9);
and the arrayGen function looks like this:
int* arrayGen(int arrAddr[], int maxNum)
{
int counter=0;
while(arrAddr[counter] != '\0') {
arrAddr[counter] = gen(maxNum);
counter++;
}
return arrAddr;
}
Right now the compilier tells me "warning: passing argument 1 of ‘arrayGen’ makes integer from pointer without a cast"
My thinking is that I pass 'a', a pointer to a[0], then since the array is already created I can just fill in values for a[n] until I a[n] == '\0'. I think my error is that arrayGen is written to take in an array, not a pointer to one. If that's true I'm not sure how to proceed, do I write values to addresses until the contents of one address is '\0'?
The basic magic here is this identity in C:
*(a+i) == a[i]
Okay, now I'll make this be readable English.
Here's the issue: An array name isn't an lvalue; it can't be assigned to. So the line you have with
a = arrayGen(...)
is the problem. See this example:
int main() {
int a[10];
a = arrayGen(a,9);
return 0;
}
which gives the compilation error:
gcc -o foo foo.c
foo.c: In function 'main':
foo.c:21: error: incompatible types in assignment
Compilation exited abnormally with code 1 at Sun Feb 1 20:05:37
You need to have a pointer, which is an lvalue, to which to assign the results.
This code, for example:
int main() {
int a[10];
int * ip;
/* a = arrayGen(a,9); */
ip = a ; /* or &a[0] */
ip = arrayGen(ip,9);
return 0;
}
compiles fine:
gcc -o foo foo.c
Compilation finished at Sun Feb 1 20:09:28
Note that because of the identity at top, you can treat ip as an array if you like, as in this code:
int main() {
int a[10];
int * ip;
int ix ;
/* a = arrayGen(a,9); */
ip = a ; /* or &a[0] */
ip = arrayGen(ip,9);
for(ix=0; ix < 9; ix++)
ip[ix] = 42 ;
return 0;
}
Full example code
Just for completeness here's my full example:
int gen(int max){
return 42;
}
int* arrayGen(int arrAddr[], int maxNum)
{
int counter=0;
while(arrAddr[counter] != '\0') {
arrAddr[counter] = gen(maxNum);
counter++;
}
return arrAddr;
}
int main() {
int a[10];
int * ip;
int ix ;
/* a = arrayGen(a,9); */
ip = a ; /* or &a[0] */
ip = arrayGen(ip,9);
for(ix=0; ix < 9; ix++)
ip[ix] = 42 ;
return 0;
}
Why even return arrAddr? Your passing a[10] by reference so the contents of the array will be modified. Unless you need another reference to the array then charlies suggestion is correct.
Hmm, I know your question's been answered, but something else about the code is bugging me. Why are you using the test against '\0' to determine the end of the array? I'm pretty sure that only works with C strings. The code does indeed compile after the fix suggested, but if you loop through your array, I'm curious to see if you're getting the correct values.
I'm not sure what you are trying to do but the assignment of a pointer value to an array is what's bothering the compiler as mentioned by Charlie. I'm curious about checking against the NUL character constant '\0'. Your sample array is uninitialized memory so the comparison in arrayGen isn't going to do what you want it to do.
The parameter list that you are using ends up being identical to:
int* arrayGen(int *arrAddr, int maxNum)
for most purposes. The actual statement in the standard is:
A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to type", where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.
If you really want to force the caller to use an array, then use the following syntax:
void accepts_pointer_to_array (int (*ary)[10]) {
int i;
for (i=0; i<10; ++i) {
(*ary)[i] = 0; /* note the funky syntax is necessary */
}
}
void some_caller (void) {
int ary1[10];
int ary2[20];
int *ptr = &ary1[0];
accepts_pointer_to_array(&ary1); /* passing address is necessary */
accepts_pointer_to_array(&ary2); /* fails */
accepts_pointer_to_array(ptr); /* also fails */
}
Your compiler should complain if you call it with anything that isn't a pointer to an array of 10 integers. I can honestly say though that I have never seen this one anywhere outside of various books (The C Book, Expert C Programming)... at least not in C programming. In C++, however, I have had reason to use this syntax in exactly one case:
template <typename T, std::size_t N>
std::size_t array_size (T (&ary)[N]) {
return N;
}
Your mileage may vary though. If you really want to dig into stuff like this, I can't recommend Expert C Programming highly enough. You can also find The C Book online at gbdirect.
Try calling your parameter int* arrAddr, not int arrAddr[]. Although when I think about it, the parameters for the main method are similar yet that works. So not sure about the explanation part.
Edit: Hm all the resources I can find on the internet say it should work. I'm not sure, I've always passed arrays as pointers myself so never had this snag before, so I'm very interested in the solution.
The way your using it arrayGen() doesn't need to return a value. You also need to place '\0' in the last element, it isn't done automatically, or pass the index of the last element to fill.
#jeffD
Passing the index would be the preferred way, as there's no guarantee you won't hit other '\0's before your final one (I certainly was when I tested it).

Resources