Passing pointers as argument in C functions - c

I read all the answered questions on this topic I could find, but none answer my question...
I am still reading about pointers in C and now I am trying to understand how pointers can be passed through a function. However, there is something I dont understand in the following code (taken from tutorialspoint.com):
#include <stdio.h>
/* function declaration */
double getAverage(int *arr, int size);
int main () {
/* an int array with 5 elements */
int balance[5] = {1000, 2, 3, 17, 50};
double avg;
/* pass pointer to the array as an argument */
avg = getAverage( balance, 5 ) ;
/* output the returned value */
printf("Average value is: %f\n", avg );
return 0;
}
double getAverage(int *arr, int size) {
int i, sum = 0;
double avg;
for (i = 0; i < size; ++i) {
sum += arr[i];
}
avg = (double)sum / size;
return avg;
}
When getAverage(balance, 5) is called, I am passing in a pointer to the first element of the balance array (as I learned in my last question). But how are we accessing the actual content of the array (sum += arr[i]) in the for loop inside getAverage?
I read the following source: http://c-faq.com/aryptr/aryptrequiv.html, I am pretty sure the sentence after the second footnote is explaining this. But I still dont understand it.
Any help is appreciated!

In getAverage, arr points to the first element of balance, as you noted. So *arr can be used to access that first element (either reading it or writing it), just as balance[0] would do in the caller.
To access the second element, you can add one to the pointer before dereferencing it, i.e. *(arr + 1), and so on. This is in fact equivalent to arr[1]. In particular, arr[i] is equivalent to *(arr + i). It adds the offset i to the address arr, scaling by the size of what's being pointed to, then dereferences the pointer.

Because arrays are allocated as a contiguous block of memory, you only need to know two things to access any element in an array:
The start position of this block of memory (i.e. arr).
The position of an element relative to the start position (i.e. the index i).
So calling arr[i] will effectively count i spaces from the array's start position, returning the value at that index.

Related

Array without the use of [] index operator [duplicate]

I am trying to print a 2D matrix with using [], instead I want to use * like a pointer.
So with a 1 D array I'd do: *(arr+i) for example.
What's the syntax used to replace in matrix[][] ?
Here's the code:
for (i = 0; i < size; i++)
{
for (j = 0; j < (size * 2); j++)
{
printf(" %5d", matrix[i][j]);
}
printf("\n");
}
P.S,
I did try several things like:
*(matrix+i+j);
*(matrix+i)+*(matrix+j);
Of course none of that worked.
Thank you for your help and time!
Use the * two times. Each of * will basically replace one []:
*(*(matrix+i)+j)
You can try this-
*(*(matrix+i)+j) //reduce level of indirection by using *
This may depend on how matrix was allocated or passed to a function.
int A[10][15];
This uses a contiguous block of memory. To address the elements without using array notation use:
A +(i*15)+j // user694733 showed this is wrong
((int *)A)+(i*15)+j // this is horribly ugly but is correct
Note the 15, as each row consists of 15 elements. Better solutions are presented in other answers here.
In the following:
int *A[10];
A is an array of 10 pointers to ints. Assuming each array element has been allocated using malloc, you address the elements without using array notation as:
*(A+i) + j;
that is, you take A, then take the ith element, dereference that and add j as the second index.
--EDIT--
And to be complete:
int foo(int *p)
here a function just receives a pointer to zero or more ints. The pointer points to a contiguous, linear block of memory into which you can place an n-dimensional array. How many dimensions there are and the upper bound of each dimension the function can only know through parameters or global variables.
To address the cells of the n-dimensional array, the programmer must calculate the addresses him/herself, using the above notation.
int foo3(int *m, int dim2, int dim3, int i, int j, int k)
{
int *cell = m + i*dim3*dim2 + j*dim2 + k;
return *cell;
}

funny characters output for a sum function (Φw ÅΩw) [duplicate]

This question already has answers here:
printf() no format string printing character and integer arrays --> garbage
(3 answers)
Closed 2 years ago.
I am having a crazy output with funny characters (Φw    ÅΩw) can i know what's wrong in the code?
probably the int main is wrong
i am obliged with int sumArray (int * a, int len , int * sum )format
#include <stdio.h>
#include <stdlib.h>
int sumArray(int *a, int len, int *sum) {
int sum1 = 0;
if (a == NULL || sum == NULL)
return -1;
int i;
(*sum) = 0;
for (i = 0; i < len; i++) {
(*sum) += a[i];
}
return 0;
}
int main() {
int *a = {1, 2, 3, 4};
int *b;
sumArray(&a, 4, &b);
printf(b);
return 0;
}
Can you try these changes ?
#include <stdio.h>
#include <stdlib.h>
int sumArray(int *a, int len, int *sum) {
// int sum1 = 0; // i removed this variable because you are not using it
if (a == NULL || sum == NULL)
return -1;
int i;
(*sum) = 0;
for (i = 0; i < len; i++) {
(*sum) += a[i];
}
return 0;
}
int main() {
// int *a = {1, 2, 3, 4};
int a[] = {1, 2, 3, 4};
int b;
// i rather declare an integer instead of a pointer to an integer
// when you declared int * b , this was a pointer, and your printf(b) was
// printing an address, not the value calculated by sumArray that is why you
// were printing funny characters
sumArray(a, 4, &b);
// a is already a pointer
printf("%d", b);
return 0;
}
You are using your pointers uninitialized. When you create a pointer, you don't know where the pointer points to. It either will be pointing to some garbage data, or in worse case, it will be pointing to a memory region which is already being used by some other program in your computer or maybe by OS itself.
If you really want to use pointers like this, you should dynamically allocate memory for them.
int* a = malloc( 4 * sizeof(int) );
int* b = malloc( sizeof(int) );
This makes sure that you can assign four integers to the memory region to which a points to. And one for b.
You then can wander in that memory using loops to assign, read or write data.
for ( int i=0; i < 4; i++ )
{
*(a + i) = i + 1;
}
Here we have a for loop which will run 4 times. Each time we are moving one block in the memory and putting the number we want there.
Remember, a is a pointer, it points to the beginning of a 4 int sized memory region. So in order to get to the next block, we are offsetting our scope with i. Each time the loop runs, a + i points to the "ith element of an array". We are dereferencing that region and assigning the value we want there.
for ( int i=0; i < 4; i++ )
{
printf("%d\n", *(a + i) );
}
And here we are using the same logic but to read data we just write.
Remember, you need to use format specifiers with printf function in order to make it work properly. printf() just reads the whatever data you happened to give it, and format specifier helps interpret that data in given format.
If you have a variable like int c = 65; when you use %d format specifier in the printf you will read the number 65. If you have %c specifier in the printf, you will read letter A, whose ASCII code happens to be 65. The data is the same, but you interpret it differently with format specifiers.
Now, your function int sumArray(int *a, int len, int *sum) accepts int pointer for the first argument. In the main function you do have an int pointer named a. But you are passing the address of a, which results in double indirection, you are passing the address of a pointer which holds address of an int array. This is not what you want, so & operator in the function call is excess. Same with b.
Call to the sumArray should look like
sumArray( a, 4, b );
And lastly, we should fix printf as well. Remember what I said about format specifiers.
And remember that b is not an int, it's int*, so if you want to get the value which b points to, you need to dereference it.
In the end, call to printf should look like
printf( "%d", *b );
Also, you should remember to free the memory that you dynamically allocated with malloc. When you use regular arrays or variables, your compiler deals with these stuff itself. But if you dynamically allocate memory, you must deallocate that memory using free whenever you are done with those pointers.
You can free a after the call to sumArray and b before terminating the main function like
free(a); and free(b);
In these kind of small projects freeing memory is probably won't cause any unwanted results, but this is a very very important subject about pointers and should be implemented properly in order to settle the better understanding of pointers and better programming practice.
In that form, your code should work as you intended.
BUT... And this is a big but
As you can see, to make such a simple task, we spent way more effort than optimal. Unless your goal is learning pointers, there is no reason to use pointers and dynamic allocation here. You could have used regular arrays as #Hayfa demonstrated above, and free yourself from a lot of trouble.
Using pointers and dynamic memory is a powerful tool, but it comes with dangers. You are playing with actual physical memory of your computer. Compilers nowadays won't let you to screw your OS while you are trying to add two numbers together but it still can result in hard to detect crashes especially in complex programs.
(Sorry if it's hard to read, I am not necessarily confident with text editor of Stack Overflow.)

Static or Pointer When "Returning" Array

I'm attempting to load an array of size n (user input), with random values. I've read that you can not return an array in C, you must use a pointer (Which is quite confusing). However, I've read that if you are storing that array to a local variable in the returning function, a pointer will not work and a static array can be used (can that be returned in a function?). Also, I've read that you are supposed to call free after using the array is open the space back up? I must be using it wrong because it crashed. So I commented it out for now. Some clarification would be great.
Here's what I have so far. When printing, it's just printing what I'm assuming is just garbage.
int* prefixAverages1(int);
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main() {
int choice;
int input;
printf("What is the size of the array?:");
scanf("%d", &input);
printf("Do you want to run prefixAverages 1 or 2?");
scanf("%d", &choice);
switch(choice) {
case 1:
printf("Beginning prefixAverages1\n");
int *a = prefixAverages1(input);
for (int i=0; i < input; i++) {
printf("%d", &i);
printf("%d \n", a[i]);
}
//free(a);
break;
}
}
int* prefixAverages1(int input) {
int x[input];
int *a = (int*)malloc(input);
srand(time(NULL));
for(int i = 0; i < input; i++) {
int s = 0;
for(int j = 0; j < i; j++) {
int r = rand() % 100;
x[j] = r;
s = s + x[j];
}
a[i] = s / (i+1);
printf("%d \n", a[i]);
}
return a;
}
I'm aware my syntax may be wonky. I haven't touched C in years, so let me know if my error is syntaxical.
edit: Values are printing as intended in the function. Added print statement in code for clairity
I'm attempting to load an array of size n (user input), with random
values. I've read that you can not return an array in C, you must use
a pointer (Which is quite confusing).
Yes, the relationship between pointers and arrays and the surprisingly wide scope of things you cannot do with arrays themselves are common points of confusion. To some extent it's a pedantic distinction. Almost everything C allows you to do with an array, it makes you do via a pointer, but it automatically converts values of array type to appropriate pointers, so that those details are largely hidden.
But in some places it pokes out. For example, there is no valid syntax that allows you even to try to declare a function that returns an array.
In other places it is actively misleading. For example, you can declare a function that appears to accept an array as an argument, but the standard explicitly specifies that the argument is actually a corresponding pointer (and that's what naturally falls out when you call such a function anyway). Specifically:
int foo(int x[3]);
is 100% equivalent to
int foo(int *x);
However, I've read that if you
are storing that array to a local variable in the returning function,
a pointer will not work
That's not so much about arrays specifically, but rather about automatic variables in general. These logically cease to exist when they go out of scope -- at the end of the innermost block in which they are declared -- so pointers to or into such objects are no longer valid once the function returns. One way to obtain such a pointer value is for the function to return it. That in itself is OK, but you cannot safely dereference such a pointer value.
and a static array can be used (can that be
returned in a function?).
The lifetime of static variables of any type is the whole execution of the program. Therefore, it is safe and can be meaningful to return a pointer (in)to a static variable from a function. But although it can work to return a pointer to a static array from your function, you still cannot return such an array itself.
Also, I've read that you are supposed to
call free after using the array is open the space back up?
You should free memory that you have allocated with one of the memory allocation functions (malloc() etc.), and no other. But when you allocate memory inside a function, you can give the caller responsibility for freeing that memory by returning the pointer to it, among other ways.
In fact, most of what you demonstrate in your example code is fine in those regards. However, you do make a key error that undermines your program. Here:
int *a = (int*)malloc(input);
You allocate input bytes and store the pointer to them in a, but that is not enough storage for input objects of type int. The size of an int varies from implementation to implementation, but the minimum size permitted by the standard is two bytes, in the most common size is four bytes. To allocate space for input objects of type int, the basic idiom is
int *a = malloc(input * sizeof(int));
Personally, though, I prefer
int *a = malloc(input * sizeof(*a));
because then I get the correct size no matter what type the pointer's referenced type is, and even if I change it later.
The fact that you treated the allocated space as if it were larger than it really was likely explains much of your program's misbehavior, including the crash when you tried to free the allocated memory.
First of all malloc takes an inparam of no of bytes not absolute array size - so change this line:-
int *a = (int*)malloc(input);
to
int *a = malloc(input*sizeof(int));
Secondly, to debug incorrect values being printed put a print in your function prefixAverages1 :-
...
...
a[i] = s / (i+1);
printf("%d \n", a[i]);
...
In main print, get rid of the first print.. this is probably making you think printing incorrect values.. The address of the local loop counter variable will look like garbage
printf("%d", &i);
OR if you wanted to track the indexes of the array elements as well modify it to :-
printf("%d", i);
You must introduce the free back to avoid leaking memory
And you should follow #AustinStephens's suggestion and avoid using a second function
This works as far as having a function that loads an array with random values:
void randomValues(int arr[], int size);
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main() {
int i;
int input;
int *array;
printf("What is the size of the array?: ");
scanf("%d", &input);
array = malloc(sizeof(int) * input);
randomValues(array, input);
for(i = 0; i < input; ++i)
printf("array[%d] = %d\n", i, array[i]);
free(array);
return 0;
}
void randomValues(int arr[], int size) {
int i;
int r;
srand((int) time(0));
for(i = 0; i < size; ++i) {
r = rand() % 100;
arr[i] = r;
}
}

C modifying array unexpected behaviour

I understand it is not possible to pass an array to a function in C and modify it without using sending a reference to that array, so how is the chess method initialising the array, and it is being printed correctly in main?
int chess(int rows, int cols, int array[rows][cols])
{
/* Go through the rows and colums in the array */
for (int i = 0; i < rows;i++)
{
for (int j = 0; j < cols; j++)
{
/* If the location is even, then print a 0, else print a 1. */
if (((i + j) % 2) ==0)
{
array[i][j] = 0;
}
else
{
array[i][j] = 1;
}
}
}
/* return */
return 0;
}
int main(void)
{
int arrayDimensions;
int noOfTests = 7;
/* run the program for the given amount of tests */
/*for (arrayDimensions = 0; arrayDimensions <= noOfTests; arrayDimensions++)*/
{
/* Declare an array for each dimension */
int array[6][5];
/* call the chess method passing it the arguments specified. */
chess(6, 5, array);
/* Print out the array according to the size of the array. */
for (int i = 0; i < 6; i++)
{
printf("\n");
for (int j = 0; j < 5; j++)
{
printf("%d", array[i][j]);
}
}
/* Create a new line after each row */
printf("\n");
}
}
Though you probably already know most of this, the latter part is relevant, so stay with this for a moment.
What you probably know
C is a pass-by-value language. This means when you do this:
void foo(int x)
{
x = 5;
}
called as
int n = 1;
foo(n);
printf("%d\n", n); // n is still 1
the caller passes a value and the parameter x receives it. But changing x has no effect on the caller. If you want to modify a caller's data variable, you must do so by-address. You do this by declaring the formal parameter to be a pointer-to-type, dereference the pointer to modify the pointed-to data, and finally, pass the address of the variable to modify:
void foo(int *p)
{
*p = 5;
}
called as:
int n = 1;
foo(&n);
printf("%d\n", n); // n is now 5
Why do you care?
So what does any of this have to do with your array? Arrays in C are a contiguous sequence of data of the underlying type of the array, and an array's expression value is the address of its first element.
Chew on that last sentence for a minute. That means the same way an int variable has a value of the int stored within, an array variables has the address of its first element as its "value". By now you know that pointers hold addresses. Knowing that and the previous description means this:
int ar[10];
int *p = ar;
is legal. The "value" of ar is its first-element address, and we're assigning that address to p, a pointer.
Ok then, So the language specifically defined arrays as parameters as simply pointers to their first elements. Therefore both of these are equivalent:
void foo(int *p)
{
*p = 5;
}
void bar(int ar[])
{
ar[0] = 5;
}
And the caller side:
int ar[10];
foo(ar); // legal, ar's "value" is its first element address
bar(ar); // legal, identical to the above.
A phrase I often use when explaining the fundamentals of pointers and arrays is simply this:
A pointer is a variable that holds an address; an array is a variable that is an address.
So whats with this whacky syntax?
int chess(int rows, int cols, int array[rows][cols])
Ah. There is something interesting. Your compiler supports VLA s (variable length arrays). When compiling the code for this function the compiler generates the proper logic to perform the proper access to the passed array. I.e. it knows that this:
array[1][0]
is cols many int values past the beginning of the array. Without the feature of VLAs (and some C compilers don't have them), you would have to do this row-by-column math yourself by hand. Not impossible, but tedious none-the-lesss. And i only briefly mention that C++ doesn't support VLA's; one of the few features C has that C++ does not.
Summary
Arrays are passed by address because when it comes to their "value", that is all they really are: an address.
Note: I worked very hard to avoid using the word "decay" or the phrase "decays to a pointer" in this description precisely because that verb implies some mystical functional operation when in-fact none exists. Arrays don't "decay" to anything. They simply are; Their "value", per the C standard, is the address of their first element. Period. What you do with that address is another matter. And as an address, a pointer can hold their "value" and dereference to access said-same (such as a function parameter).
Personal: I once asked on this forum how long that term (decay) has been buzzed about in C-engineer vernacular, since in the 600+ pages of the C standard it appears exactly ZERO times. The farthest back anyone found was 1988 in the annals of some conspicuous online journal. I'm always curious to note who started it an where, and said-quest continues to elude me.
Anyway, I hope this helps, even a little.
when dealing with arrays you are dealing with an address so if you pass an array into a function and you changed the array in the function, the real array will change.
In other words, if you know pointers an array is a pointer.
I didn't read the code but you have a clear misunderstanding of passing an array to a function.
An array reference IS an address (it's a misnomer to say it's a pointer, but it will behave as such). It works because the function is declared to accept a type of int[][], which allows the function to interact with the array reference as if you'd passed a pointer to the function.
From a reference manual:
When a function parameter is declared as an array, the compiler treats
the declaration as a pointer to the first element of the array. For
example, if x is a parameter and is intended to represent an array of
integers, it can be declared as any one of the following declarations:
int x[]; int *x; int x[10];
So you are passing a reference. The compiler turns your declaration into a pointer reference with also some sizing constraints.

Array of pointers to arrays

I am new to C programming and this is my problem:
I want to store the first value of each array in a new array, then the second value of each array in a new array and so on.
I could declare the array of pointers but I don't know how I use it!
Please I need Help.
int main()
{
int t1[4]={0,1,2,3};
int t2[4]={4,5,6,7};
int t3[4]={8,9,10,11};
int t4[4]={12,13,14,15};
int *tab[4]={t1,t2,t3,t4};
int i,j,k,l;
for (i=0; i<4;i++)
{
printf("%d\t", *tab[i]);
}
return 0;
}
When I do this, I store just the first value of each array.
Your terminology is a little bit all over the place. I think the easiest way to answer your question is to go through your code line by line.
int main()
{
int t1[4]={0,1,2,3}; //Declares a 4 integer array "0,1,2,3"
int t2[4]={4,5,6,7}; //Declares a 4 integer array "4,5,6,7"
int t3[4]={8,9,10,11}; //Declares a 4 integer array "8,9,10,11"
int t4[4]={12,13,14,15}; //Declares a 4 integer array "12,13,14,15"
int *tab[4]={t1,t2,t3,t4};//Declares a 4 pointer of integers array "address of the first element of t1, address of the first element of t2, ..."
int i,j,k,l; //Declares 4 integer variables: i,j,k,l
for (i=0; i<4;i++)
{
printf("%d\t", *tab[i]); //print out the integer that is pointed to by the i-th pointer in the tab array (i.e. t1[0], t2[0], t3[0], t4[0])
}
return 0;
}
Everything you are doing seems ok until your loop. You are showing only the first integer of every array because you are not going through them. To iterate over them, your code should look like this:
for (i=0; i<4;i++)
{
for (j=0; j<4; j++)
{
printf("%d\t", *(tab[j] + i));
}
}
The above code uses two loop counters, one (the i) to go through the positions in the array (first value in the array, second value in the array, etc.); the other to go through the different arrays (the j). It does this by retrieving the pointer stored in tab[j] and creating a new pointer that has the right offset to show the value for the ith column. This is called pointer arithmetic (there is additional information about pointer arithmetic here)
Most people find the syntax *(tab[j] + i) to be clunky, but it is more descriptive of what is actually happening. In C, you can rewrite it as tab[j][i], which is much more usual.
You have stored the data as you intended, you just need to access it properly
for (i=0; i<4;i++)
{
for (j = 0; j < 4; j++) {
int* temp = tab[i];
printf("%d\t", temp[j]); // or try the next line...
printf("%d\t", *(temp + j)); // prints same value as above line
printf("%d\t", tab[i][j]; // the same value printed again
}
}
All of the above print the same value, it is just different ways of accessing that value using pointer arithmetic. Each element of tab is a int* the value of each is the address of your other defined int[] arrays at the start
Edit: In response to the comment of Jerome, you can achieve that by declaring 4 arrays
int tab1[4]={*t1,*t2,*t3,*t4};
int tab2[4]={*(t1+1),*(t2+1),*(t3+1),*(t4+1)};
int tab3[4]={*(t1+2),*(t2+2),*(t3+2),*(t4+2)};
int tab4[4]={*(t1+3),*(t2+3),*(t3+3),*(t4+3)};
Now tab1 contains the first elements of each array, tab2 the second elements, and so on.
Then you can use
int *tttt[4]={tab1,tab2,tab3,tab4};
for (i=0; i<4;i++) {
for (j = 0; j < 4; j++) {
printf("%d\t", tttt[i][j]);
}
}
to print what you wanted. If you declared another pointer array like you did at the start
int* tab[4] = {t1,t2,t3,t4};
then essentially in matrix terms, tttt is the transpose of tab
You store everything but you just don't show it. Try
for (i=0; i<4;i++)
{
for (j=0; j<4; j++)
printf("%d\t", *(tab[i]+j));
}
int* (*a[5])[5][5][5] declares an array of 5 pointers to a 3d array of pointers to ints
int* (*(*a[5])[5])[5][5][5] declares an array of 5 pointers to an array of 5 pointers to a 3d array of pointers to ints.
#include <stdio.h>
int main()
{
int t1[4]={0,1,2,3};
int t2[4]={4,5,6,7};
int t3[4]={8,9,10,11};
int t4[4]={12,13,14,15};
int (*tab[4])[4]={&t1,&t2,&t3,&t4};
int i,j,k,l;
for (i=0; i<4;i++)
{
printf("%d\t", (*tab[i])[1]);
}
return 0;
}
There's a difference between t2 and &t2. Though they have the same value their types are different. int [4] vs int (*)[4]. The compiler will throw a warning (clang) or error (gcc).
int a[4] is conceptually at compiler level a pointer to an array of 4 as well as being the array itself (&a == a).
int (*a)[4] is conceptually at compiler level a pointer to a pointer to an array of 4 as well as being a pointer to the array itself (a == *a) because it's pointing to an array type where the above is true.
At runtime, if an int * and int (*a)[4] point to the same address, they are physically identical – it's just an address, the same address. The type only matters in how the compiler interprets and produces arithmetic operations with that address and the assembly it actually outputs based on the type. You can cast the address to any type you want in order to achieve the desired code output to manipulate data at the address it holds. An int a[4] type however is physically the array itself but you use it as if there is a pointer a to it in memory which is given the same address as the array itself. A pointer to int a[4] means 'a pointer to the address range a that is treated by the compiler as an array with int element width, where the compiler treats the start of the array as if it were a pointer to the array', and any operations on that type will be consistent in a derefernce chain i.e. you must at compiler level use (*a)[0] to access the first element if the type is a pointer to an array, but if you cast the same address to int * then you need to use a[0] to access the member.

Resources