The exercise says "Make a function with parameters two int arrays and k which is their size. The function should return another array (size k) where every element of it is the sum of the two arrays of the same position. That's what I wrote, but it crashes. Do I have to do it with pointers?
#include <stdio.h>
#include <stdlib.h>
void sumarray(int k,int A[k],int B[k]){
int sum[k],i;
for(i=0;i<k;i++){
sum[i]=A[i]+B[i];
printf("sum[%d]=%d\n",i,sum[i]);}
}
main(){
int i,g,a[g],b[g];
printf("Give size of both arrays: ");
scanf("%d",&g);
for(i=0;i<g;i++){
a[i]=rand();
b[i]=rand();
}
sumarray(g,a,b);
system("pause");
}
Example: If i have A={1,2,3,4} and B={4,3,2,1} the program will return C={5,5,5,5).
This:
int i,g,a[g],b[g];
causes undefined behaviour. The value of g is undefined upon initialisation, so therefore the length of a and b will be undefined.
You probably want something like:
int i, g;
int *a;
int *b; // Note: recommend declaring on separate lines, to avoid issues
scanf("%d", &g);
a = malloc(sizeof(*a) * g);
b = malloc(sizeof(*b) * g);
...
free(a);
free(b);
Its impossible to first do a[g] when dynamically getting g.
Your first lines in main should be:
int i,g;
int *a,*b;
printf("Give size of both arrays: ");
scanf("%d",&g);
a = (int *)malloc(g*sizeof(int));
b = (int *)malloc(g*sizeof(int));
int sum[k] ;
k is a variable but the size of the array should be a constant.
The function should return another array (size k) ...
But the function you wrote returns void which is clearly wrong.
Do I have to do it with pointers?
Yes.
One issue is that you've attempted to declare dynamically sized arrays on the stack (e.g. a[g]). You need to declare pointers for each array and then dynamically allocate your variable sized array once you've read in the value of g.
change the function summary signature (the definition part of the declaration) to this and try it out:
void sumarray(int k,int* A,int* B){
Related
I don't understand where the error is in the function.I need to print 2 arrays with random elements.
int *boo3(int *x , int n){
x = (int*) malloc(sizeof(int)*n);
int i;
for(i=0;i<n;i++){
x[i] = rand()%10-(rand()%10);;
printf("%5d ",x[i]);
}
printf("\n");
}
int main(int argc, char *argv[])
{
int *x ,*y;
int n , m;
int i,j;
printf("enter size of X[n]: ");
scanf("%d",&n);
printf("enter size of Y[m]: ");
scanf("%d",&m);
x=boo3(*x,n);
y=boo3(*y,m);
free(x);
free(y);
return 0;
}
There are several problems with this code:
x = (int*) malloc(sizeof(int)*n); overwrites the function parameter x.
No return statement in boo3,
x=boo3(*x,m) in this line, *x is dereferencing pointer x which gives you int
In main function, you tried to free uninitialized pointer x and y
In your code
int *boo3(int *x , int n)
This indicates that you should receive a return value from this function.
In general a return value can be error code or any data which you might want to use going ahead.
Just like a math function for addition, taking operands as an argument and returning the sum. In your case, it is a pointer to the memory you have been allocated with.
In boo3() function, you are allocating some memory and you need the pointer to that memory for further usage. boo3() doesn't return anything, however, in main() function, you are assuming that you have caught it, hence the problem.
You should return the pointer to data from boo3().
I can see in main() function,
x=boo3(*x,n);
This is alarming. You are dereferencing a int* pointer and passing an int (instead of int*) as an argument to boo3() function which expects a int*.
If you wish to assign the pointer declared in main() with the address of memory allocated in boo3(), then you don't catch it and change to
boo3(x, n);
boo3(y, m);
And change to
void boo3(int *x , int n)
However, ideally, the function should return and the value be caught as a return value. In that case, change to
int* boo3(int n)
At the end of boo3 add a return x;. And use it as
x = boo3(n);
Additionally, you are not checking if the malloc() has allocated any memory or not. You should check if the pointer is NULL to see if memory is allocated. It is minimum error-checking and handling you need to have. Secondly, malloc() returns a void*, so the typecast is needless.
The problem is, you do not return anything from the function boo3(), and try to use the return value. This causes undefined behavior.
You need to add a return x; at the end of the function so as to return the pointer holding the address of the allocated memory (and populated values).
That said, passing the pointer argument is not needed when you return the pointer from the function. Apart from the fact that your call does not even try to pass a pointer as the first argument, as expected by the function signature - to allocate memory to a pointer from a called function, you need to pass the address of the pointer anyways, passing the pointer alone will not suffice. You don't need to do that, just define the function as
int *boo3(int n) { //......
and in the end, add
return x;
and from main(), call it like
x=boo3(n);
y=boo3(m);
There are many issues in your code.
Following has been corrected:
boo3 now simply returns the pointer to the allocated memory filled with random numbers, the useless x parameter has been removed and the function now contains the missing return statement. This is actually the main problem in your code.
The pointless (int*) cast has been removed from malloc.
The code is formatted properly.
Variables are declared as close as possible to their scope. This is the idiomatic way, declaring all variables at the start of the scope is a thing from the last century.
Usage of meaningful variable names.
This is a correct version of your program:
#include <stdlib.h>
#include <stdio.h>
int* boo3(int n) {
int *array = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
array[i] = rand() % 10 - (rand() % 10);;
printf("%5d ", array[i]);
}
printf("\n");
return array;
}
int main(int argc, char* argv[])
{
int sizex, sizey;
printf("enter size of X[n]: ");
scanf("%d", &sizex);
printf("enter size of Y[m]: ");
scanf("%d", &sizey);
int *xvalues = boo3(sizex);
int *yvalues = boo3(sizey);
free(xvalues);
free(yvalues);
return 0;
}
Disclaimer: for brevity there is no error checking for scanf and malloc.
I will go straight to what I'm asking for, I also see some similar question but is not what I'm looking for...so it seems I have to ask with a new forum.
I'm preparing myself for a future examination, where is not required the pointer, but I would like to get some extra information and abilities.
Here's the code followed by the question...
I'm using Fedora 33, I know is different from some IDE on Windows (ex: Visual Studio or Dev C++)
/* It's just a simple test, if this work I will get myself into a more complicated one, as you could read in the
* forum, I'm getting ready ( just a recheck of my abilities ) for an universitary examinaton. */
#include <stdio.h>
#include <stdlib.h>
#define N 5
void casual_generation(int** mat);
void prompt_print(int** mat);
int main()
{
int **mat[N][N];
casual_generation(**mat);
prompt_print(**mat);
}
void casual_generation(int** mat)
{
int i=0,j=0;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
mat[i][j] = rand() % 50;
}
void prompt_print(int** mat)
{
int i=0,j=0;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
printf("%d ", mat[i][j]);
printf("\n");
}
}
Somebody else on the forum used malloc, struct or other stuff, as you can see in this picture, when I try to execute him it says "Segmentation fault (core dumped)"
screen error
Where is my error?
And if you want, can you also send me the version with the passed value pointer?
Thanks for whoever will give me an answer, and time dedicated.
This declaration
int **mat[N][N];
does not make a sense. It means that you have a matrix elements of which are pointers of the type int **. But you need a matrix elements of which are integer numbers of the type int. That is you need a declaration like this
int mat[N][N];
So now you have a two-dimensional array (or matrix) of integers.
As you are going to pass this two-dimensional array to functions then used as an argument expression it is converted to pointer to its first element of the type int ( * )[N].
Correspondingly the functions that accepts such an array should be declared like
void casual_generation( int mat[][N], size_t n );
void prompt_print( int mat[][N], size_t n );
or (that is fully equivalent) like
void casual_generation( int ( * mat )[N], size_t n );
void prompt_print( int ( *mat )[N], size_t n );
because the compiler adjusts function parameters having array types to pointers to array element types.
Now for example the first function can be defined the following way
void casual_generation( int ( * mat )[N], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < N; j++ )
{
mat[i][j] = rand() % 50;
}
}
}
And the function can be called like
casual_generation( mat, N );
A similar way can be defined the function prompt_print.
Using the second parameter makes the function more general. For example it can be called for two-dimensional arrays with different numbers of rows.
Now I will explain why you are getting a segmentation fault in your original code.
You have this declaration
int **mat[N][N];
a two dimensional array of pointers of the type int **.
Then you are using the expression **mat as an argument of function calls like this
casual_generation(**mat);
Then you are applying the dereference operator like *mat the array designator is converted to pointer to its first element (row) having the type int ** ( * )[N]. So dereferencing this pointer you get the first row of your array int **[N]. Applying the second time the dereferenced operator to this expression that has an array type the used expression is again is converted to pointer to its first element of the type int **( * ). That is it points to the first element of the first row of the original two-dimensional array. Dereferencing this pointer you get the first element of the type int **. This uninitialized pointer with indeterminate value the function accepts as its argument.
Thus dereferencing this first uninitialized element of the original matrix within the function
mat[i][j] = rand() % 50;
^^^
you get a segmentation fault. The reason of the fault is the incorrect matrix and the corresponding function parameter as it was shown above in tbe beginning of the answer.
Where is my error?
The "Segmentation fault" error happens because you define the variable mat as a pointer, but don't allocate any memory for it to point to.
int **mat[N][N];
You meant to do
Int mat[N][N];
and
casual_generation(mat);
prompt_print(mat);
By passing **mat you are passing mat[0][0] that is an int, but you want to pass the whole matrix which is a pointer to pointers to int (i.e. int **)
And you may want to introduce srand() in your code.
Just to make things clear:
mat is of type int ** and it's the whole matrix (or if you want it's a pointer to the first row)
*mat is of type int * and it's the first row of the matrix (or if you want it's a pointer to the first element of the first row)
**mat is of type int and it's the first element of the first row of the matrix
int **mat[N][N];
Here, you defined a double pointer to a 2D array. You only need to use one of those - a double pointer or a 2D array, like so:
int mat[N][N];
However, the bigger problem comes from trying to interchange 2D arrays and double pointers. This isn't possible in C since the 2D array is laid out flat in memory.
You need to create an array mat_ptr of pointers yourself and then pass that to casual_generation and prompt_print.
Finally, these casual_generation and prompt_print functions expect to be given a pointer, so you shouldn't dereference the pointer with ** before calling the function.
The final working code is:
int main()
{
int mat[N][N];
int *mat_ptr[N];
for (int i = 0; i < N; i++)
mat_ptr[i] = mat[i];
casual_generation(mat_ptr);
prompt_print(mat_ptr);
}
As you can find a detailed explanation why the code crashed in the other answer I will only propose a quite elegant solution that uses a neat though little known feature from C99 called Variable Length Arrays (aka VLA).
#include <stdio.h>
#include <stdlib.h>
void casual_generation(int n, int mat[n][n]);
void prompt_print(int n, int mat[n][n]);
int main()
{
const int N = 5;
int mat[N][N];
casual_generation(N, mat);
prompt_print(N, mat);
}
void casual_generation(int n, int mat[n][n])
{
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
mat[i][j] = rand() % 50;
}
void prompt_print(int n, int mat[n][n])
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%d ", mat[i][j]);
printf("\n");
}
}
It compiles in pedantic mode with no warnings and it works like a charm.
VLA were introduced to C to simplify numerical computation over multidimensional arrays.
#include <stdio.h>
void print(int (*p)[3]);
int main(void)
{
int a[3] = {1, 2, 3};
print(&a);
return 0;
}
void print(int (*p)[3])
{
for (int i = 0; i < sizeof(*p) / sizeof(**p); i++)
printf("%d\n", (*p)[i]);
}
I have written a C function. See above.
It can print all the elements in an array.
There is one thing which is not so perfect : The number of array elements seems to be known in advance.
So I made some modification in hopes of making the function universal :
#include <stdio.h>
void print(int (*p)[]);
int main(void)
{
int a[3] = {1, 2, 3};
print(&a);
return 0;
}
void print(int (*p)[])
{
for (int i = 0; i < sizeof(*p) / sizeof(**p); i++)
printf("%d\n", (*p)[i]);
}
In the function, p is pointer pointing to the entire array.
However, it fails to be compiled.
Why can't int (*p)[] be used as an argument for C function?
int (*p)[] can be used as an argument for the function. The part of your code that gives the error is sizeof *p which is obviously not possible, because the type of *p is int[] which is an incomplete type and hence has no known size.
For the function to know the length of the array, you must design a way for the function to receive this information. Options include:
what you did in the original code.
passing the length as another argument.
including the length as an array element.
having a sentinel value on the end of the array.
The most common idiom would be to pass int *p, size_t n, you do not really gain anything by using pointer-to-array without the dimension being given.
The problem is that int [] is an incomplete type as the array has no defined size and therefore its sizeof cannot be taken.
In "modern C" (i.e. for almost 2 decades) you could have used variable-length arrays for this - you can pass the size as an argument and then the array:
#include <stdio.h>
#include <stdlib.h>
void print(size_t n, int (*p)[*]);
int main(void) {
int a[3] = {1, 2, 3};
print(3, &a);
}
void print(size_t n, int (*p)[n]) {
for (size_t i = 0; i < sizeof(*p) / sizeof(**p); i++)
printf("%d\n", (*p)[i]);
}
Of course this gains you nothing, since sizeof *p / sizeof **pp will be ... n. Therefore we might as well have used
void print(size_t n, int p[n]) {
for (size_t i = 0; i < p; i++)
printf("%d\n", p[i]);
}
which is less typing.
Short answer: int (*p)[] can't be used as an argument and have the function magically know the array size, because the standard says so.
Longer answer:
int (*p)[] is a pointer to an array, but the array has no defined size. So by looking at the array, it is impossible to do pointer arithmetic, calculate size of the thing p is pointing at, etc..
You don't have array of arrays so you don't need int (*p)[]. You have an array of int, so int *p or int p[] should be enough. This does not solve the problem of knowing the size of your array in print. To do this you basically have 3 options
Hardcode the value in the function
Put a sentinel value in your array to mark the end
Pass the size as a separate parameter like this:
void print(int n, int p[n])
Just remember that whatever method you use, parameter passing of arrays will always use pointers behind the scenes, so you CAN NOT use sizeof(p) to calculate the size of the array. sizeof will always return the size of a pointer in those situations
I have been learning arrays, but theres one thing that I cant figure out.
I borrowed two books for C and looked online, but found no solution.
My function timesTen multiplies every array elemenet that I have by 10,
then returns pointer of that array back function main()
How can I copy array a[2] directly in array x[2]?
I would usually use for loop, but I cant, because arguments are in two different functions.
Solution has probably got something to do with pointers, so feel free to post sollution here, but is there any way around them aswell?
Heres the source code:
#include <stdio.h>
int timesTen(int a[])
{
int i;
for (i=0;i<2;i++)
{
printf("%d\t", a[i]);
a[i]*=10;
printf("%d\n", a[i]);
}
return a;
}
int main()
{
int i;
int x[2];
int a[2]={10,50};
// i know here's an error, but how do I fix it? I cant put x[0]=timesTen(a[0])
x[2] = timesTen(a);
//also what if there is array a[10], and I want to copy it in x[5]
for (i=0;i<2;i++)
printf("%d\n", x[i]);
return 0;
}
Thanks!
What you need to understand is the distinction between arrays and pointers. When you declare your two arrays in main(), you allocate two times memory for two integers. That's fine. But in C, you simply cannot pass arrays around (as in: implicitly allocate a new slap of memory and copy the data of the source array into this memory region). Instead, any array identifier will decay to a pointer to the first element of the array in almost all situation. So when you write
int x[2];
int a[2]={10,50};
timesTen(a);
this code is precisely equivalent to
int x[2];
int a[2]={10,50};
timesTen(&a[0]);
So, why does that not clash with your declaration of timesTen()? Because array parameters in function declarations decay right there, on the spot, into a pointer! So, your function declaration is precisely equivalent to this one:
int timesTen(int* a) {
This is one of the least understood features of the C language, and admittedly, it is hard to wrap your brain around this, but once you understand what pointer decay means, you will be much more at ease using pointers and arrays.
So, back to your question. Since you passed only a pointer to your array to timesTen(), and since you modify this array, the changes are directly visible in main(). There are two ways to achieve the behavior you want:
You can change the definition of timesTen() to copy the data into a destination array:
void timesTen(int size, int* source, int* dest) {
for(int i = 0; i < size; i++) dest[i] = 10*source[i];
}
int main() {
int x[2];
int a[2]={10,50};
timesTen(2, a, x); //pointer decay!
//x now contains {100, 500}
}
You can copy the data into the destination array before calling your function to modify the destination array:
void timesTen(int size, int* data) {
for(int i = 0; i < size; i++) data[i] = 10*data[i];
}
int main() {
int x[2];
int a[2]={10,50};
memcpy(x, a, sizeof(a)); //the sizeof operator is one of only two places where no pointer decay happens!
timesTen(2, x); //pointer decay!
//x now contains {100, 500}
}
In the function timesTen, since a is an array, each modification made to it in the function is also done to the parameter you passed (call by address not by value). Therefore you don't need to returns anything.
void timesTen(int a[])
{
int i;
for (i=0;i<2;i++) a[i]*=10;
}
And you just call it by:
timesTen(a);
You probably want something like this:
timesTen(a);
memmove(x, a, 2 * sizeof(x[0]));
instead of
x[2] = timesTen(a);
Note that your function does not need to return anything, because it is modifying the array on its original place. In C if you have an array parameter, it means that only a pointer is passed, not the whole array.
in main function:
int *p;
int i;
p = timesTen(a);
for ( i = 0; i < 2; i++ )
{
printf( "%d\n",*(p + i)); // here you can print the values returned from your function
}
Through pointers you could have eaisly managed it
main ()
{
int a[ 2 ];
int *ptr = timesTen(a);
for ( int i=0; i<2 ; i++)
{
printf("%d",ptr[i]);
}
And as far as
x[2] = timesTen(a);
Is concerned note that x[2] will give "value at 2nd adress from adrees of base that is x"
And it is not a variable but it is a value and you cant assign to a value.
Technically x[2] is not a lvalue.
I just started programming so pointers and arrays confuse me.
This program just assigns random numbers from 0 - 9 into array and prints them out
(#include <stdio.h> #include <stdlib.h> #include <time.h>)
int function(int *num[]){
int i;
for(i=0; i<10; i++){
srand((unsigned)time(NULL));
*num[i] = rand()%10;
printf("%d", *num[i]);
}
return 0;
}
int main(){
int num[10];
function(&num); // incompatable pointer type (how do i fix this?)
return 0;
}
Thankyou
Change your code to read something like this:
int function(int num[]){
int i;
for(i=0; i<10; i++){
srand((unsigned)time(NULL));
num[i] = rand()%10;
printf("%d", num[i]);
}
return 0;
}
int main(){
int num[10];
function(num);
return 0;
}
In main(), you are allocating an array of 10 integers. The call to function(num) passes the address of this array (technically, the address of the first element of the array) to the function() function. In a parameter declaration, int num[] is almost exactly equivalent to int *num (I'll let you ponder on that one). Finally, when you access the elements of num[] from within the function, you don't need any extra *. By using num[i], you are accessing the i'th element of the array pointed to by num.
It may help to remember that in C, the following are exactly the same:
num[i]
*(num+i)
You don't need to pass in a pointer to your array. Just pass in the array. I have fixed your pointer code below.
Also, you should not reset the seed (srand) through every iteration through the for loop.
int function(int num[]){
int i;
srand((unsigned(time(NULL));
for(i=0; i<10; i++){
num[i] = rand()%10;
printf("%d", num[i]);
}
return 0;
}
int main(){
int num[10];
function(num);
return 0;
}
It all depends on what you want to achieve in the end.
(1) If your function function is intended to be used with arrays of run-time size, then you have to pass a pointer to the first element of the array. That is achieved by the following equivalent declarations
int function(int *num)
or
int function(int num[])
Inside the function you have to access the passed array as
num[i] = rand() % 10;
And you call your function as
function(num);
Of course, when the array size is a run-time value, it makes sense to pass that size to the function as well, meaning that your function should have the following interface
int function(int num[], size_t n)
And implement it for an array of size n, instead of hardcoding 10 directly into your implementation.
(2) If your function function is intended to be used with arrays of fixed compile-time size (10 in this case), then the better approach would be to pass a pointer to the entire array. It is achieved by the following declaration
int function(int (*num)[10])
Inside the function you have to access the passed array as
(*num)[i] = rand() % 10;
And you call your function as
function(&num);
So it is either (1) or (2).
What you currently have in your code looks like a mix of these two approaches. More precisely, you code looks like an attempt to implement the second approach, but it is missing some important parentheses :)
Most answers given to you so far suggest using the first approach. However, seeing that the array size is actually a compile-time constant in your case, I would suggest sticking with the second approach.
Use either int *num or int num[], don't use both together as you have right now (int *num[]). An array is passed to a function as a pointer to the first element, i.e. int *num, which is equivalent to int num[].