I frequently use the following convention to inform client code that a function requires an argument of an array with defined size:
/* File foo.h */
int foo (int arg[10]);
The message I want to give to client code is that they must provide an array of type int with 10 positions.
I am aware that it is not very usual, so I came here to ask: Am I missing any side effect of this convention ? Is it anyhow harmful?
Thank!
If you want to insist on getting an array of size 10, you can use:
int foo (int (*arg)[10]);
The ill-side effects of this are:
In the function, you have to use:
(*arg)[index]
instead of just
arg[index]
The calling function must use:
int array[10];
foo(&array);
instead of
int array[10];
foo(array);
You cannot use an array that has more than 10 elements.
int array[20];
foo(&array); // Not OK.
You cannot use a malloced array.
int* array = malloc(sizeof(int)*10);
foo(array); // Not OK.
Now pick the solution that is least harmful.
struct arrayContainerTen{
int data[10];
}
void aFunction(struct arrayContainerTen *pAnArray)
{
size_t size = sizeof(pAnArray->data);
}
main()
{
arrayContainerTen anArray;
aFunction(&anArray);
}
There's no harm in writing it like this. But just be aware that the compiler will not enforce the requirement. A declaration like that is treated by the compiler as if you'd written.
int foo(int *arg);
Related
I am having problems accessing a matrix and vector with variable size using malloc() realloc() functions in a subalgorithm. I have tried the following but it doesn't seem to work.
int main()
{
char nombre[50];
sprintf(nombre,"data.txt");
int **red;
int *links;
int i, j, colSize;
links = (int*)malloc(Nred*sizeof(int));
red = (int**)malloc(Nred*sizeof(int*));
for(i=0; i<Nred; i++)
{
red[i]=(int*)malloc(1*sizeof(int));
}
LeeRed(*red, *links, Nred, nombre, &colSize);
}
void LeeRed (int ***mat, int **links, int nNodes, char *nombre, int *colSize)
{
int i, j, maxSize, nodo1, nodo2;
FILE *f, *g;
f=fopen(nombre,"rt");
g=fopen("matrizPrueba.txt", "w");
maxSize=0;
/// Number of links per node starts at 0
for(i=0; i<nNodes; i++)
{
*links[i]=0;
}
//...
}
First things first, * is the dereference operator, not the create reference operator. When you pass your matrix and links to your function, you should use & instead. For example:
LeeRed(&red, &links, Nred, nombre, &colSize);
This will make all of your types match. I would be shocked if your compiler didn't warn you about this (if it's not, try recompiling with -Wall). That being said, you really shouldn't be passing a pointer to your matrix unless you plan on modifying the pointer to your matrix. You might want to do this if you were planning on reallocating the matrix for some reason, but in the function above just make your life easier and pass the pointers by value. So change your function signature to:
void LeeRed (int **mat, int *links, int nNodes, const char *nombre, int *colSize);
Also, when you access an array with a pointer, you do not need to dereference it first, so you can use links[i] instead of *links[i]. And be careful with your allocations, right now you have an Nredx1 matrix allocated, but if you reallocate any of those columns without freeing them, you'll have a memory leak on your hands. Be sure to free everything you allocate (from the bottom up, calling free(red) will not free the columns, you must do those individually).
I'm also not sure what the links variable is intended to do, but it may be redundant if you're just trying to read into a matrix. I can't help you any further without more context.
The types of the first two parameters don't match what you're passing in.
red has type int ** and links has type int *, and you're passing *red and *links which have types int * and int respectively. This differs from the int *** and int ** types that your function is expecting for these parameters.
You're also calling the function before it's been defined or declared, so it has an implicit declaration of int LeeRead() which doesn't match the actual definition.
You should pass these two parameters directly without dereferencing:
LeeRed(red, links, Nred, nombre, &colSize);
Change the parameter types to match:
void LeeRed (int **mat, int *links, int nNodes, char *nombre, int *colSize)
Change how these two parameters are used in the function accordingly, and move the function's definition to above main.
It seems there are many questions of the form "should I declare X?" but not this specific one. I hope it is ok to ask this.
The title says it all: why should I declare a pointer? Even better: there are risks if I do not declare the pointer? Consider the following examples:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <string.h>
void func(int *ptr);
int main (int argc, char **argv)
{
int a;
int *PTRa;
a = -1;
PTRa = &a;
func(PTRa);
printf("%d\n", a);
return 0;
}
void func(int *ptr)
{
*ptr = 1;
return;
}
I get a=1. In this case I would say the pointer is declared (and assigned as well): I have the line int *PTRa; (declaration) and the line PTRa = &a; (assignment). The results is correct. I don't get any warning.
Imagine now to replace the main with the following:
int main (int argc, char **argv)
{
int a;
a = -1;
func(&a);
printf("%d\n", a);
return 0;
}
Here I do not declare the pointer but just give the address of a to func. The result is correct and I don't get warnings.
My understanding is that the two approaches are identical: func always gets the same input, the address of a. I would even dare to say that I feel the second approach to be better, as I feel it to be clearer and I feel the variable PTRa to be useless and somewhat redundant. However, I always see codes where the first approach is used and I have the feeling I will be told to do so. Why?
You are correct: there's no point in declaring a pointer in your example. A pointer is just a variable that holds an address. The cleaner approach is to pass directly the address of the variable: func(&a) instead of doing one extra step and declaring PTRa.
Note that not all cases are this simple. For example, if you want to have an array of ints, but you want to be able to grow that array dynamically because you don't know how big it should be you have to declare a pointer:
int count = ...; // get the count from the user, from a file, etc
int *list_of_ints = malloc(sizeof(int) * count);
if (list_of_ints == NULL)
{
// malloc failed.
printf("Not enough memory!\n");
exit(1);
}
// Now `list_of_ints` has enough space to store exactly `count` `int`s
EDIT: as #paulsm4 pointed out in a comment, the question Why use pointers? is a great source of information related to this topic.
EDIT 2: one good reason to want a pointer to the address of a variable might be that you want a pointer inside a structure or array:
struct foo
{
int x;
};
struct bar
{
int y;
struct foo f;
};
struct bar b;
struct foo *ptr_foo = &b.f;
You can now work more easily with b.f because you're just working with a struct foo.
In this case there's no benefit in creating a separate pointer variable.
It might be necessary in more complex cases, just like it's sometimes necessary to create variables of any other type.
From the title, I thought you're talking about pointer type, but actually, you are asking if declaring a variable is needed.
Variable is a piece of memory, storing some numbers(bytes), and the type of the variable, indicating how you and your program interpret those bytes: integer? float? character? etc.
Pointer is the memory address, it could be of a variable, or a function, or something else.
A variable of pointer is a small area in the memory, storing the address of other(or even same) memory.
You decide if you need an extra variable to store the pointer. It's the same to the decision that if you want a variable to store an integer:
int v = -1;
abs(v); // use variable
abs(-1); // use constant
I'm a bit confused at the difference here, in C99:
int myfunc (int array[n], int n) { ... }
will not compile. As far as I know you must always put the reference to the array size first, so it has to be written:
int myfunc (int n, int array[n]) { ... }
But if you supply the static keyword, this works absolutely fine:
int myfunc (int array[static 1], int n) { ... }
This order if far preferable to me, as I'm used to having arrays come first in a function call, but why is this possible?
Edit: Realising that the third example isn't actually a VLA helps...
For reference, this was the piece of code I was looking at that led to the question:
int sum_array(int n, int m, int a[n][m])
{
int i, j, sum = 0;
for (i = 0; i < n; i++)
for (j = 0; j < m; j++)
sum += a[i][j];
return sum;
}
The reason why
int myfunc (int n, int array[n]) { ... }
is valid and
int myfunc (int array[n], int n) { ... }
is not is due to the lexical scoping rules of C. An identifier cannot be used before it has been introduced in the scope. There are a few exceptions to this rule but this one is not one of them.
EDIT: here is the relevant paragraph of the C Standard:
(C99, 6.2.1p7) "Any other identifier has scope that begins just after the completion of its declarator."
This rule also applies to parameters declaration at function prototype scope.
The reason for error has already been explained to you: you have to declare n before you can use it in other declarations.
However, it is worth noting that none of these declarations actually declare variable length arrays, as you seem to believe.
It is true that syntax with [n] was first allowed in C99 and that it is formally a VLA declaration, but nevertheless in the given context all of these declarations declare array as a parameter of int * type, just like it has always been in C89/90. The [n] part is not a hint of any kind. The fact that you can use [n] in this declaration is indeed a side-effect of VLA support, but this is where any relationship with VLA ends. That [n] is simply ignored.
A "hint" declaration requires keyword static inside the []. So, your declaration with [static 1] is equivalent to classic int array[1] declaration (meaning that 1 is ignored and the parameter has type int *) except that it gives the compiler a hint that at least 1 element must exist at the memory location pointed by array.
It's because arrays must be declared with a constant value so you cannot create an array using a variable size and therefore cannot pass an array with a variable size. Also if it is just a single-dimension array you don't need to pass a value in at all, that is the point of passing in the second parameter to tell you the length of your array.
To get this to work properly just write the function header like this:
int myfunc (int myArray[], int n) {...}
The order shouldn't matter, but you cannot have the size of an array you are passing be variable it must be a constant value.
If you are using GCC and are willing to use some of their extensions, you can accomplish what you wish right here:
int myFunc (int len; /* notice the semicolon!! */ int data[len], int len)
{
}
The documentation for this extension (Variable Length Arrays) is here.
Please note that this extension is NOT available in clang for some reason, I'm not quite sure why, though.
EDIT: Derp, scope, of course.
My question is; why do you need to do it at all? You're really getting a pointer anyway (you can't pass arrays to a function in C, they degrade to a pointer, regardless of the function's signature). It helps to let the caller know the expected size of the input, but beyond that it is useless. Since they are already passing the size, just use...
int myfunc(int arr[], size_t size) {
// ...
}
Or
int myfunc(int *arr, size_t size) {
// ...
}
I have an array/pointer related problem.
I created an int array myArray of size 3. Using a function I want to fill this array.
So I'm calling this function giving her the adress &myArray of the array.
Is the syntax correct for the function declaration`? I'm handing over the pointer to the array, so the function can fill the array elements one by one.
But somehow my array is not filled with the correct values.
In Java I could just give an array to a method and have an array returned.
Any help is appreciated! Thanks!
#include <stdio.h>
int myArray[3];
void getSmth(int *anArray[]);
int main(void)
{
getSmth(&myArray);
}
void getSmth(int *anArray[])
{
for(i=0...)
{
*anArray[i] = tmpVal[i];
}
}
Remove one level of indirection:
#include <stdio.h>
int myArray[3];
void getSmth(int anArray[]);
int main(void)
{
getSmth(myArray);
}
void getSmth(int anArray[])
{
for(i=0...)
{
anArray[i] = tmpVal[i];
}
}
Also, as others have suggested, it would be a good idea to pass the size of the array into getSmth().
No, the syntax is not correct. You have an extra *, making the argument into an array of pointers.
In general, it's better to use:
void getSmth(int *array, size_t length);
since then the function can work on data from more sources, and the length becomes available which is very handy for iterating over the data as you seem to want to be doing.
You'd then call it like so:
int main(void)
{
int a[12], b[53];
getSmth(a, sizeof a / sizeof a[0]);
getSmth(b, sizeof b / sizeof b[0]);
}
Note the use of sizeof to compute (at compile-time) the number of elements. This is better than repeating the numbers from the definitions of the variables.
Right now, your function accepts an int *anArray[] parameter, which is an array of pointers to int. Remove the unneccessary * and your function signature should look simply like this:
void getSmth(int anArray[]); // array of int
or
void getSmth(int *anArray); // pointer to first array element of type int
You should use either int anArray[] or int *anArray (which is effectively the same, because array decays to pointer). You should also make sure that the function knows how big your array is either by agreement or passing it as a parameter for it can not use sizeof for the purpose.
Even though it is possible to write generic code in C using void pointer(generic pointer), I find that it is quite difficult to debug the code since void pointer can take any pointer type without warning from compiler.
(e.g function foo() take void pointer which is supposed to be pointer to struct, but compiler won't complain if char array is passed.)
What kind of approach/strategy do you all use when using void pointer in C?
The solution is not to use void* unless you really, really have to. The places where a void pointer is actually required are very small: parameters to thread functions, and a handful of others places where you need to pass implementation-specific data through a generic function. In every case, the code that accepts the void* parameter should only accept one data type passed via the void pointer, and the type should be documented in comments and slavishly obeyed by all callers.
This might help:
comp.lang.c FAQ list ยท Question 4.9
Q: Suppose I want to write a function that takes a generic pointer as an argument and I want to simulate passing it by reference. Can I give the formal parameter type void **, and do something like this?
void f(void **);
double *dp;
f((void **)&dp);
A: Not portably. Code like this may work and is sometimes recommended, but it relies on all pointer types having the same internal representation (which is common, but not universal; see question 5.17).
There is no generic pointer-to-pointer type in C. void * acts as a generic pointer only because conversions (if necessary) are applied automatically when other pointer types are assigned to and from void * 's; these conversions cannot be performed if an attempt is made to indirect upon a void ** value which points at a pointer type other than void *. When you make use of a void ** pointer value (for instance, when you use the * operator to access the void * value to which the void ** points), the compiler has no way of knowing whether that void * value was once converted from some other pointer type. It must assume that it is nothing more than a void *; it cannot perform any implicit conversions.
In other words, any void ** value you play with must be the address of an actual void * value somewhere; casts like (void **)&dp, though they may shut the compiler up, are nonportable (and may not even do what you want; see also question 13.9). If the pointer that the void ** points to is not a void *, and if it has a different size or representation than a void *, then the compiler isn't going to be able to access it correctly.
To make the code fragment above work, you'd have to use an intermediate void * variable:
double *dp;
void *vp = dp;
f(&vp);
dp = vp;
The assignments to and from vp give the compiler the opportunity to perform any conversions, if necessary.
Again, the discussion so far assumes that different pointer types might have different sizes or representations, which is rare today, but not unheard of. To appreciate the problem with void ** more clearly, compare the situation to an analogous one involving, say, types int and double, which probably have different sizes and certainly have different representations. If we have a function
void incme(double *p)
{
*p += 1;
}
then we can do something like
int i = 1;
double d = i;
incme(&d);
i = d;
and i will be incremented by 1. (This is analogous to the correct void ** code involving the auxiliary vp.) If, on the other hand, we were to attempt something like
int i = 1;
incme((double *)&i); /* WRONG */
(this code is analogous to the fragment in the question), it would be highly unlikely to work.
Arya's solution can be changed a little to support a variable size:
#include <stdio.h>
#include <string.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[size];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int array1[] = {1, 2, 3};
int array2[] = {10, 20, 30};
swap(array1, array2, 3 * sizeof(int));
int i;
printf("array1: ");
for (i = 0; i < 3; i++)
printf(" %d", array1[i]);
printf("\n");
printf("array2: ");
for (i = 0; i < 3; i++)
printf(" %d", array2[i]);
printf("\n");
return 0;
}
The approach/strategy is to minimize use of void* pointers. They are needed in specific cases. If you really need to pass void* you should pass size of pointer's target also.
This generic swap function will help you a lot in understanding generic void *
#include<stdio.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[100];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int a=2,b=3;
float d=5,e=7;
swap(&a,&b,sizeof(int));
swap(&d,&e,sizeof(float));
printf("%d %d %.0f %.0f\n",a,b,d,e);
return 0;
}
We all know that the C typesystem is basically crap, but try to not do that... You still have some options to deal with generic types: unions and opaque pointers.
Anyway, if a generic function is taking a void pointer as a parameter, it shouldn't try to dereference it!.