I had to write a program which has a function that sums all positive number in an array, but using function parameter array as an pointer. There in main function a problem occurs, when i try to call sum function. here is my source code:
#include <stdio.h>
#include <conio.h>
int posit(int *x[], int n){
int s=0;
for(int i=0; i<n; i++){
if(*x[i]>0){
s=s+*x[i];
}
}
return s;
}
int main(){
int k;
scanf("%d",&k);
int a[k];
for(int i=0; i<k; i++){
scanf("%d",&a[i]);
}
int b=posit(&a,k);
printf("%d\n", b);
getch();
return 0;
}
When an array is passed to a function it decays to a pointer to its first element. Change the signature of the function to:
int posit(int* x, int n){ /* Equivalent to 'int posit(int x[], int n)' */
and change the element access syntax of the array in the function from *x[i] to just x[i]. The invoke the function:
int b=posit(a,k);
Another point worth mentioning is to check the return value of scanf(), which returns the number of assignments made, to ensure &a[i] is actually being assigned and the program is subsequently not using uninitialized variables.
You may find the Arrays and Pointers section of the C FAQ useful.
Actually in your example you are passing to function pointer to pointer (please note that similar notation is very often used with main argument char *argv[]).
As mentioned in hmjd post while passing array to function this is converted to address of its first element. Instead of explicitly using pointer (int *x) you can also use array notation (int[] or even int[k]) but those are the same.
Please also note that in second method (int[k]) size provided doesn't matter and inside function it will be not known. This is only important to include size when you are dealing with multiple dimension arrays, but this is other story...
From K&R2
When an array name is passed to a function, what is passed is the
location of the initial element. Within the called function, this
argument is a local variable, and so an array name parameter is a
pointer, that is, a variable containing an address.
So you will be passing only the first element to the function.
Once this is understood your source can be modified as follows
int posit(int *x, int n)
and to call this function from main you can use
int b=posit(a,k); //Note only the location of the first element is being passed
Related
I am having trouble passing a pointer array to a function. I will post a simple example that still doesn't work for me. Could you please tell me what I am doing wrong?
#include <stdio.h>
#include <stdlib.h>
int transformare(int *v[1])
{
*v[1] = 10;
return 0;
}
int main()
{
int v[1];
printf("n = ");
scanf("%d", &v[1]);
transformare(&v);
printf("%d", v[1]);
return 0;
}
You have two problems:
Array indexes are zero-based. That is, an array of N elements have indexes from 0 to N - 1 (inclusive)
The declaration int *v[1] declares v as an array of one pointer to int, not as a pointer to an array of one int. That would be int (*v)[1]. Which is also the type of &v from the main function.
The solution to the second problem (using the correct type) then leads to a third problem, as it means that *v[0] is incorrect due to operator precedence. You need to use parentheses here too, as in (*v)[0].
However the second (and the following third) problem is moot, since you don't need to pass arrays "by reference".
Arrays naturally decays to pointers to their first element. When using plain v when a pointer to int is expected, the compiler will automatically translate it as &v[0].
That means you could declare the function to simply take an int * as argument, and simply pass plain v as the argument.
First, please note that indizes are 0-based in C, i.e. the first (and - in your case only) element is v[0].
Concerning passing it, just define the parameter as pointer to int, i.e. int*. A variable of type int[1] will decay to a pointer to int when passed to a function (so there is no need to write transformare(&v), its transformare(v).
int transformare(int *v)
{
v[0] = 10;
return 0;
}
int main()
{
int v[1];
printf("n = ");
scanf("%d", &v[0]);
transformare(v);
printf("%d", v[0]);
return 0;
}
I just want to print out a static array (2D array) in C using functions. I use gcc as my compiler. When I try to run my code it gives me a seg fault and I dont have any idea why:
#include <stdio.h>
void print_out_an_array(int n, int m, int tab[n][m])
{
int i,j;
for(i=0; i<n; i++)
for(j=0; j<m; j++)
printf("tab[%d][%d] = %d\n", i, j, tab[i][j]);
}
int main(int argc, char **argv)
{
int tab[2][4] = {{1,2,3,4}, {5,6,7,8}};
print_out_an_array(tab, 2, 4);
return 0;
}
your function call and function definition doesnt match
your function call
print_out_an_array(tab, 2, 4);
but in function definition your first argument is int
void print_out_an_array(int n, int m, int tab[n][m])
make the arguments same, like:
change function call to
``print_out_an_array(2, 4, tab);`
update:
check this code it works
and also read this for reference C, passing 2 dimensional array
In your function definition, first parameter is int type but you are calling your function with first argument as int **. Change your function call to
print_out_an_array(2, 4, tab);
About the question in your comment:
Ok, but how about this code: http://ideone.com/Z4mHkb why it gives me an error?
Function parameters **tab and tab[n][m] are not equivalent. Compiler, on seeing tab [m][n] as function parameter, interprets it as
void fun(int (*)[m]tab, int n, int m)
i.e , it interprets tab as a pointer to an array of m integers. While on seeing int **tab, it simply interprets tab as a pointer to a pointer to integer (or an array of pointers ( int *tab[]) to int ).
Instead of answering the original solution whose solution is obvious, I answer the other one from your comment.
Your array is a
int[][N]
while you pass a
int ** to your function.
These are completely different from each other:
An int[][N] has all values from all dimensions beneath each other.
An int **, however, points to one or more pointers, in turn pointing to the real values.
At int[][], you can omit one level of indirection and can turn it into a
int (*)[N]
i. e. a pointer to an array. This array must be of determined size, which isn't fulfilled in your case as well.
I have a question regarding passing address of first element of an array to a (recursive) function:
selectionSort( &b[1], size-1);
When address is passed to a function, function parameter must be a pointer as I know. selectionSort method gets int b[] as argument. Not a pointer.
But code works without any problems. Also this code generates subarrays. When we pass the 1st element does it become the subarray's zeroeth element?
void selectionSort(int b[], int size)
{
int temp,i;
if (size>=1)
{
for (i = 0; i < size; i++)
{
if (b[i]<b[0])
{
temp=b[0];
b[0]=b[i];
b[i]=temp;
}
}
selectionSort( &b[1], size-1 );
}
}
Whenever you have a function like:
void f(int b[]);
this is the same as
void f(int *b);
The [] syntax for function parameters is just a special syntax to let the reader know that you intend to use the parameter like an array, but it is actually just a pointer. You can't pass an actual array to a function. Pointers and arrays work very similarly in C, so for the most part you can work with a pointer as if it were an array (but be careful -- there are important exceptions).
For example, when you access an element of an array like this:
array[index]
this is the same as
*(array+index)
and it doesn't matter whether array is a real array or just a pointer.
So &b[1] is the same as &*(b+1), which is the same as b+1.
If we were to write the code so that we see the b parameter as a pointer, it would look like this:
void selectionSort(int *b, int size){
.
.
.
selectionSort( b+1, size-1 );
.
.
.
}
Now, you can see that selectionSort is being passed a pointer to an int, and it calls itself with a pointer to the next int.
Yes, the code will create 'sub arrays' you should use:
A pointer to an array of integers
selectionSort(int (*b)[], int size)
And call the function using:
selectionSort( &b[1], size-1 );
Below is a snippet from the book C Programming Just the FAQs. Isn't this wrong as Arrays can never be passed by value?
VIII.6: How can you pass an array to a function by value?
Answer: An array can be passed to a function by value by declaring in
the called function the array name
with square brackets ([ and ])
attached to the end. When calling the
function, simply pass the address of
the array (that is, the array’s name)
to the called function. For instance,
the following program passes the array
x[] to the function named
byval_func() by value:
The int[] parameter tells the
compiler that the byval_func()
function will take one argument—an
array of integers. When the
byval_func() function is called, you
pass the address of the array to
byval_func():
byval_func(x);
Because the array is being passed by
value, an exact copy of the array is
made and placed on the stack. The
called function then receives this
copy of the array and can print it.
Because the array passed to
byval_func() is a copy of the
original array, modifying the array
within the byval_func() function has
no effect on the original array.
Because the array is being passed by value, an exact copy of the array is made and placed on the stack.
This is incorrect: the array itself is not being copied, only a copy of the pointer to its address is passed to the callee (placed on the stack). (Regardless of whether you declare the parameter as int[] or int*, it decays into a pointer.) This allows you to modify the contents of the array from within the called function. Thus, this
Because the array passed to byval_func() is a copy of the original array, modifying the array within the byval_func() function has no effect on the original array.
is plain wrong (kudos to #Jonathan Leffler for his comment below). However, reassigning the pointer inside the function will not change the pointer to the original array outside the function.
Burn that book. If you want a real C FAQ that wasn't written by a beginner programmer, use this one: http://c-faq.com/aryptr/index.html.
Syntax-wise, strictly speaking you cannot pass an array by value in C.
void func (int* x); /* this is a pointer */
void func (int x[]); /* this is a pointer */
void func (int x[10]); /* this is a pointer */
However, for the record there is a dirty trick in C that does allow you to pass an array by value in C. Don't try this at home! Because despite this trick, there is still never a reason to pass an array by value.
typedef struct
{
int my_array[10];
} Array_by_val;
void func (Array_by_val x);
Isn't this wrong as arrays can never be passed by value?
Exactly. You cannot pass an array by value in C.
I took a look at the quoted part of the book and the source of this confusion or mistake is pretty fast found.
The author did not know about that *i is equivalent to i[] when provided as a parameter to a function. The latter form was invented to explicitly illustrate the reader of the code, that i points to an array, which is a great source of confusion, as well-shown by this question.
What I think is funny, that the author of the particular part of the book or at least one of the other parts (because the book has 5 authors in total) or one of the 7 proofreaders did not mentioned at least the sentence:
"When the byval_func() function is called, you pass the address of the array to byval_func():"
With at least that, they should had noticed that there is a conflict.
Since you passing an address, it is only an address. There is nothing magically happen which turns an address into a whole new array.
But back to the question itself:
You can not pass an array as it is by value in C, as you already seem to know yourself. But you can do three (there might be more, but that is my acutal status of it) things, which might be an alternative depending on the unique case, so let´s start.
Encapsulate an array in a structure (as mentioned by other answers):
#include <stdio.h>
struct a_s {
int a[20];
};
void foo (struct a_s a)
{
size_t length = sizeof a.a / sizeof *a.a;
for(size_t i = 0; i < length; i++)
{
printf("%d\n",a.a[i]);
}
}
int main()
{
struct a_s array;
size_t length = sizeof array.a / sizeof *array.a;
for(size_t i = 0; i < length; i++)
{
array.a[i] = 15;
}
foo(array);
}
Pass by pointer but also add a parameter for determine the size of the array. In the called function there is made a new array with that size information and assigned with the values from the array in the caller:
#include <stdio.h>
void foo (int *array, size_t length)
{
int b[length];
for(size_t i = 0; i < length; i++)
{
b[i] = array[i];
printf("%d\n",b[i]);
}
}
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
foo(a,(sizeof a / sizeof *a));
}
Avoid to define local arrays and just use one array with global scope:
#include <stdio.h>
int a[10];
size_t length = sizeof a / sizeof *a;
void foo (void)
{
for(size_t i = 0; i < length; i++)
{
printf("%d\n",a[i]);
}
}
int main()
{
for(size_t i = 0; i < length; i++)
{
a[i] = 25;
}
foo();
}
In C and C++ it is NOT possible to pass a complete block of memory by value as a parameter to a function, but we are allowed to pass its address. In practice this has almost the same effect and it is a much faster and more efficient operation.
To be safe, you can pass the array size or put const qualifier before the pointer to make sure the callee won't change it.
Yuo can work it around by wrapping the array into the struct
#include <stdint.h>
#include <stdio.h>
struct wrap
{
int x[1000];
};
struct wrap foo(struct wrap x)
{
struct wrap y;
for(int index = 0; index < 1000; index ++)
y.x[index] = x.x[index] * x.x[index];
return y;
}
int main ()
{
struct wrap y;
for(int index = 0; index < 1000; index ++)
y.x[index] = rand();
y = foo(y);
for(int index = 0; index < 1000; index ++)
{
printf("%d %s", y.x[index], !(index % 30) ? "\n" : "");
}
}
#include<stdio.h>
void fun(int a[],int n);
int main()
{
int a[5]={1,2,3,4,5};
fun(a,5);
}
void fun(int a[],int n)
{
int i;
for(i=0;i<=n-1;i++)
printf("value=%d\n",a[i]);
}
By this method we can pass the array by value, but actually the array is accessing through the its base address which actually copying in the stack.
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[].