C newbie here, I need some help: Can anyone explain to (and offer a workaroud) me why this works:
int n=1024;
int32_t data[n];
void synthesize_signal(int32_t *data) {
...//do something with data}
which let me alter data in the function; but this does not?
int n=1024;
int number=1024*16;
int32_t data[n][2][number];
void synthesize_signal(int32_t *data) {
...//do something with data}
The compiler error message is something like it expected int32_t * but got int32_t (*)[2][(sizetype)(number)] instead.
First, passing arrays in C is by reference. So you pass a pointer of some sort, and the function can modify the data in the array. You don't have to worry about passing a pointer to the array. In fact, in C there is no real different between a pointer that happens to be to the being of an array, and the array itself.
In your first version. You making a one-dimensional array data[n], and you are passing it to your function. In the array, you'll using it by saying, something like data[i]. This translates directly to (data + (i sizeof(int32_t)). It is using the size of the elements in the array to find the memory location that is i positions in front of the beginning of your array.
int n=1024;
int number=1024*16;
int32_t data[n][2][number];
void synthesize_signal(int32_t *data)
In the second case, you're setting up a mufti-dimensional array (3D in your case). You setup correctly. The problem is that when you pass it to the function, the only thing that gets passed the address of the being of the array. When it gets used inside the function, you'll do something like
data[i][1][x] = 5;
Internally C is calculating how from the beginning of the array this location is. In order for it to do that, it need to know the dimensions of the array. (Unlike some newer languages, C store any extra data about array lengths or sizes or anything). You just need to change the function signature so it knows the shape/size of array to expect. Because of the way, it calculates array positions, it doesn't need the first dimension.
In this case, change your function signature to look like this:
void synthesize_signal(int32_t data[][2][number]) { ...
Setup the array the same way you are doing the second one above, and just call it you'd expect:
synthesize_signal(data);
This should fix everything for you.
The comments mention some useful information about using more descriptive variable names, and global vs. local variable. All valid comments to keep in mind. I just addressed to code problem you're having in terms of mufti-dimensional arrays.
try
synthesize_signal(int32_t** data)
{
}
Your function also needs to know that data is multi dimensional. You should also consider renaming your data array. I suspect that it is a global variable and using the same name in function can lead to problems.
When you call the function, do it like this:
synthesize_signal(&data[0][0][0]);
Related
before you mark this as a duplicate please notice that I'm looking for a more general solution for arrays of arbitrary dimensions. I have read many posts here or in forums about making 2D or 3D arrays of integers but these are specific solutions for specific dimensions. I want a general solution for an array of any dimension.
First I need to have a type of intlist as defined below:
typedef struct{
int l // length of the list
int * e // pointer to the first element of the array
}intlist;
this actually fills the gap in C for treating arrays just as pointers. using this type I can pass arrays to functions without worrying about loosing the size.
then in the next step I want to have a mdintlist as multidimensional dynamically allocated arrays. the type definition should be something like this:
typedef struct Mdintlist{
intlist d // dimension of the array
/* second part */
}mdintlist;
there are several options for the second part. on option is that to have a pointer towards a mdintlist of lower dimension like
struct Mdintlist * c;
the other options is to use void pointers:
void * c;
I don't know how to continue it from here.
P.S. one solution could be to allocate just one block of memory and then call the elements using a function. However I would like to call the elements in array form. something like tmpmdintlist.c[1][2][3]...
Hope I have explained clearly what I want.
P.S. This is an ancient post, but for those who may end up here some of my efforts can be seen in the Cplus repo.
You can't! you can only use the function option in c, because there is no way to alter the language semantics. In c++ however you can overload the [] operator, and even though I would never do such an ugly thing (x[1][2][3] is alread y ugly, if you continue adding "dimensions" it gets really ugly), I think it would be possible.
Well, if you separate the pointers and the array lengths, you end up with much less code.
int *one_dem_array;
size_t one_dem_count[1];
int **two_dem_array;
size_t two_dem_count[2];
int ***three_dem_array;
size_t three_dem_count[3];
This way you can still use your preferred notation.
int num_at_pos = three_dem_array[4][2][3];
When I am trying to pass two dimensional array as a parameter In C,
void PrintTriangle(int *triangle)
It's doesn't works for me why ?
You must specify the dimension of the outermost array when passing multidimensional arrays as parameters
Something like this:-
void PrintTriangle(int pascalTriangle[][5]);
Calling PrintTriangle(pascalTriangle); like this is wrong as your function PrintTriangle() is expecting a pointer to integer.
Here's how I memorized passing multidemensional arrays as parameters. This might be a little childish but works for me.
Suppose You have an array defined
int numbers[3][4];
and you want to pass it to function.
To do it correctly I answer series of questions:
1) What do I want to pass to function? An array.(in this case numbers).
2) What's numbers? Numbers is an address of its first element(without going into details);
3)What's the first element of numbers?(in this case it's an array of 4 integers)
4) So what I want as function formal parameter is a pointer to answer from step 3:
int (*pointer)[4]
It might be slow and looks unprofessional but you can ask the same question on array of every dimension you can think of. It's also useful to ask yourself that when not passing whole array but one of subarrays.
Hope it helps you as it helped me.
Calling your function as
PrintTriangle(pascalTriangle);
is wrong. Because PrintTriangle() expecting a pointer to integer as its argument and pascalTriangle (after decaying) is of type int(*)[5].Also you must have to pass the number of rows and columns (as arguments) in array pascalTriangle. Prototype for this function should be
void PrintTriangle(int row, int col, int *triangle);
and a call to it may be
PrintTriangle(5, 5, &pascalTriangle[0][0]);
I want to pass a 2d array i defined using malloc to a function.
First i define the array using code from a blog post.
int** Make2DIntArray(int arraySizeX, int arraySizeY) {
int** theArray;
theArray = (int**) malloc(arraySizeX*sizeof(int*));
for (int i = 0; i < arraySizeX; i++)
theArray[i] = (int*) malloc(arraySizeY*sizeof(int));
return theArray;
}
int main(){
int** myArray = Make2DIntArray(nx, ny);
}
I can then use it as myArray[i][j].
After that,i want to pass this array to a function.I tried to pass it like this:
function(myArray); //function call
//function
void function(int myArray[][]){
//function code goes here
}
but this is wrong.The problem is that the size of the array is different every time.I also tried to define a maximum size for the columns of the array and use it like this:
#define COLUMNMAX 100
function(myArray); //function call
//function
void function(int myArray[][COLUMNMAX]){
//function code goes here
}
but i got the error:
type of formal parameter 1 is incomplete.How can i pass it?
The parameter is a int**
And you don't have to cast the return of malloc, just check if it's not NULL
But since you use malloc don't use free when you don't need it anymore
myArray bounds are not know so you should change void function(int myArray[][]){ to void function(int **myArray){.
Do not make typecasting of malloc
The C standard supports variable-length arrays, so you do not need to allocate, assign, or use extra pointers. Simply specify the dimensions you want, as shown below.
Allocate an array of M rows of N columns like this:
int (*array)[N] = malloc(M * sizeof *array);
Declare a function that is receiving such an array like this:
void function(size_t M, size_t N, int array[][N]);
Pass the array to the function like this:
function(M, N, array);
What you do with Create2DIntArray is not an actuall 2d array. It's just an array of pointers, each pointing to some place in memory. And every piece of memory is allocated separately with separate malloc call (BTW, don't forget to free it). So basically there's no guarantees, that there bits are allocated consequentionally and properly alligned as with int myArray[][]. The only way to pass your data as a 2d array, I guess, would be to create a real 2d array and refill it with your data.
To get rid of your "type of formal parameter 1 is incomplete." error, you should declare your function before you use it (forward declaration):
void functionB(int **myArray); //forward declaration
void functionA() {
functionB(blaaaa); //usage
}
void functionB(int **myArray) {
//implementation
}
It looks like what you're needing here is some booking information for the size of the rows and columns in the array. There are multiple ways to do that, but here are four)
1) If you know the size at compile time, you could use a define like you tried to do. Defines are globally scoped, you can access them in all your functions in a file. Instead of somehow trying to pass the defined value (like COLUMN_SIZE ) simply use it as a for loop end-condition inside your "function" function. However, if you know the size before compile time, you might as well simply make an array of fixed size. Malloc is usually meant for dynamic run-time determined memory allocation.
2) Simply store the values of nx and ny in main, and make it so that "function" takes 3 arguments: (int[][] my_array, column_size, row_size) and pass it your pointer to the array as well as nx and ny. This is preferable than method 1, because it allows for an array size to be specified during runtime, not during compile time.
3)This is the one I would recommend: Use a structure, like this
struct 2d_array{
int row_size;
int column_size;
int** actual_array;
}
With this, you have a few options. You could edit Make2dIntArray so that it returns either a 2d_array structure or a pointer to a 2d_array structure (depending on if you want to handle the structure with pass by reference or pass by value). Or you could have it so that you construct the structure in main. I'd advise having Make2dIntArray return the structure, it would be very clean.
And then you could have your "function" function simply take a 2d_array structure as it's argument (again, either as a pointer or not, depending on if you want to change the row_size and column_size variables, which I can't see any purpose for unless you remalloc actual_array). Then you just access the row_size and column_size variables in the structure inside "function" and you have all the information you need.
Basically, the whole idea behind this is book-keeping. Keep track of the information you need, and make it easily accessible when you need it.
I am dusting off my C skills working on some C libraries of mine. After having put together a first working implementation I am now going over the code to make it more efficient. Currently I am on the topic of passing function parameters by reference or value.
My question is, why would I ever pass any function parameter by value in C? The code might look cleaner, but wouldn't it always be less efficient than passing by reference?
Because it's not as important to code for the computer as it is to code for the next human being. If you are passing references around then any reader must assume that any called function could change the value of his parameters and would be obligated to check it or copy the parameter before calling.
Your function signature is a contract and divides your code up so that you don't have to fit the entire code base into your head in order to comprehend what is going on in some area, by passing references you are making the next guy's life worse, your biggest job as a programmer should be making the next guy's life better--because the next guy will probably be you.
In C, all arguments are passed by value. A true pass by reference is when you see the effect of a modification without any explicit indirection at all:
void f(int c, int *p) {
c++; // in C you can't change the original paramenter passed like this
p++; // or this
}
Using values instead of pointers though, is frequently desirable:
int sum(int a, int b) {
return a + b;
}
You would not write this like:
int sum(int *a, int *b) {
return *a + *b;
}
Because it is not safe and it is inefficient. Inefficient because there is an additional indirection. Moreover, in C, a pointer argument suggests the caller that the value will be modified through the pointer (especially true when the pointed type has a size less than or equal to the pointer itself).
Please refer to Passing by reference in C. Pass by reference is a misnomer in C. It refers to passing the address of a variable instead of the variable, but you are passing a pointer to the variable by value.
That said, if you were to pass the variable as a pointer, then yes it would be marginally more efficient, but the main reason is to be able to modify the original variable it points to. If you don't want to be able to do this, it is recommended you take it by value to make your intent clear.
Of course, all this is moot in terms of one of Cs heavier data structures. Arrays are passed by a pointer to their first variable whether you like it or not.
Two reasons:
Often times you will have to dereference the pointer you've passed in many times (think a long for-loop). You don't want to dereference every single time you want to look up the value at that address. Direct access is faster.
Sometimes you want to modify the passed-in value inside you function, but not in the caller. Example:
void foo( int count ){
while (count>0){
printf("%d\n",count);
count--;
}
}
If you wanted to do the above with something passed by reference, you would haev to create yet another variable inside your function to store it first.
So in my main function I'm creating a 2D array:
int dataDim = 100;
float inData[2][dataDim];
I want to pass it to a function where I will be able to fill it up with data. How to pass it in a manner that I will be able to fill it up directly? Maybe
function(float** array)
and then accessing array[0][0] probably doesn't work? Strange how I can't find any quick example about this.
in C, multidimensional arrays' sizes must be known to pass as such, although some sizes may be omitted, if you like.
Exact
void function(float array[][100]);
void function(float (*array)[100]);
Syntactically Valid
Although the compiler may legally ignore the size 2.
void function(float array[2][100]);