How to navigate through arrays using pointers? - c

Why isn't my code working?
#include <stdio.h>
int main()
{
int test[] = { 3, 9, 7 };
printf("%d", find(test, 3));
return 0;
}
int find (int array[], int size)
{
int i, largest, where;
largest = array [0];
for (i=0; i<size; ++i) {
if (array[i]>largest) {
largest = array[i];
where = i;
}
}
return (int) *(&array+sizeof(int)*where);
}
I know I can replace:
return (int) *(&array+sizeof(int)*where);
with:
return array[where];
but that isn't the point of the exercise.

Pointer arithmetic doesn't work the you think it does. You're looking for:
return *(array + where);
array is already a pointer, and pointer arithmetic just "does the right thing" when adding.
You might be confusing yourself because of the int array[] in your function signature - that's just syntatic sugar for int *array. You really have a pointer, not an array.
Since there is some misinformation flying around in other answers, I'm going to write a more complete explanation here. This function signature:
int find(int array[], int size)
really means:
int find(int *array, int size)
The use of the [] is just syntactic sugar, as mentioned above. When you call the function, like:
find(test, 3);
test is decaying automatically into a pointer to its first element. It's identical to if you had called:
find(&test[0], 3);
Now, looking at your return statement, you can see that:
return (int) *(&array+sizeof(int)*where);
Doesn't make sense - first of all &array is the address of parameter - in this case a pointer parameter, but that doesn't really matter. If you add to it and dereference, you're going to return some random data from your stack, not not from the array you want to.
Secondly, the multiplication by sizeof(int) is unnecessary. Pointer arithmetic in C already includes an implicit multiplication by the size of the pointed-to type. What you're really trying to return is:
return array[where];
which is equivalent to:
return *(array + where);

You're greatly overcomplicating this...
return array[where]; // this means, take the base memory location of "array" then
// add in an offset of where and dereference the result
That's exactly the same as:
return *(array + where);
The fact is that in your main function you have an array called test, once you pass this to your find() function the array will decay to a pointer. So if you now know that you have a pointer you should see why you shoud not be grabbing the address like this:
&array
And you don't need to be adding the "sizeof" offset, because that's given by the type of the pointer (int *)

You should do:
return *(array+where);
since where is the offset to the array. You don't need sizeof(int) anymore

Related

Passing array by ref causes compiler warnings - How to use pointer-arithmetic correct here?

void foo(int **arr)
{
**arr = 5; // works fine, no warnings and myArray[0] is 5 after call.
*(arr+5) = 5; //warning - assignment makes pointer from integer without a cast - why?
*(arr)[5] = 5; //No warnig but programm would crash
}
int main()
{
int *myArray = (int*)calloc(10,sizeof(int));
foo(&myArray); //no warning but myArray[5] would be still 0
foo(myArray); //warning - passing argument 1 of 'foo' from incompatible pointer type (but works fine)
printf("%d",myArray[5]);
return 0;
}
How to pass the array correctly to my function and access myArray[5] without any warnings?
As written, the proper way to index into arr would be
(*arr)[5] = 5;
Since arr is a pointer to a pointer to your array, you don’t want to index into arr, you want to index into what arr points to. You need to explicitly group the * with arr since postfix operators like [] have higher precedence than unary *.
Having said that, the only reason to pass a pointer to myArray is if you expect to change the value of myArray itself, such as with a call to realloc. If that’s not the intent, then it’s better to write the function as Antti and Peter have shown.
Since foo takes a pointer to a pointer to integer, calling foo(&myArray) is correct here. But you don't need to do that at all. Simply pass in myArray and have foo take a pointer to int instead:
void foo(int *arr)
{
arr[5] = 5;
}
int main()
{
int *myArray = calloc(10, sizeof(int)); // no need to cast here unless compiling with a C++ compiler
foo(myArray);
printf("%d", myArray[5]); // prints 5
return 0;
}
I know pointers can be confusing, but there seems to be a very fundamental misunderstanding here so I recommend carefully reading the pointer section of any good C textbook again.
Like this:
#include <stdio.h>
#include <stdlib.h>
void foo(int *arr) {
arr[5] = 5;
}
int main(void) {
int *myArray = calloc(10, sizeof(int));
foo(myArray);
printf("%d", myArray[5]);
}
You only need to pass the pointer by reference if you want to change the value of the original pointer object (i.e. if you want to make the pointer stored in myArray point to another allocated memory block after calling foo).

The difference between pointer in 2D and 1D array

I practiced today some C code, especially array with return function and pointers.
And I found some code which were really confusing and want to know why it is.
So I have first a function which print all elements out of the array.
void function(int *arr)
{
...
printf("%d, arr[i]);
}
Now in main I have a 2D array and a 1D array.
int array2D[2][2] = {{1,2}, {3,4}};
int array1D[3] = {1,2,3};
function(*array2D); // Why do I need here the derefernce pointer
function(array1D); // why I don't need here the deference pointer
And in another case:
void disp( int *num)
{
printf("%d ", *num);
}
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
for (int i=0; i<10; i++)
{
/* Passing addresses of array elements*/
disp(&arr[i]); // why i need here & and above in the function not
}
}
This is really confusing me right now. Can someone explain me this?
The first line
function(*array2D);
is equivalent to
function(array2D[0]);
So you are passing the first array [1,2]. In C an array decays into a pointer
when it is passed to a function.
However, your function function1 should also get the number of
elements of the array.
void function(int *arr, size_t len)
{
size_t i;
for(i = 0; i < len; ++i)
printf("%d\n", arr[i]);
}
Then you can call it2
int array2D[2][2] = { { 1,2} ,{3,4}};
int array1D[3] = {1,2,3};
function(*array2D, sizeof *array2D / sizeof **array2D);
function(array1D, sizeof array1D / sizeof *array1D);
disp (&arr[i]); // why i need here & and above in the function not
Because arr[i] would give you the value stored at the position i, disp
expects a pointer, so you use the &-operator which returns the address of the
array at the position i, which is also equivalent to arr + i.
1Don't call your functions function. Technically that is valid name, but it
would be better if you give your function more explicit names so that just by
reading the name, you know what the functions does.
2Note that sizeof array / sizeof *array only works with arrays. If you have a
function and you expect an array, you will get only a pointer to the array.
In this case you also would need to pass the length of the array.
We're used to the fact that int mike[10] decays to int *, which points to the first thing in the array. So it seems like int sam[5][10] might also decay to int * pointing to the first element of the array. But int sam[5][10] is not a "two-dimensional array of int" that decays to an int pointer, it's an array of five arrays of ten integers. The first thing in sam is the first of the five arrays, so sam decays to a pointer to an array of ten integers, which type is written int (*)[10], though it rarely is written.
So your array2D decays to a different type than integer pointer, which is why your call function(array2D); creates a type mismatch. But your call function(*array2D); does work because (as noted above) *array2D is the same as array2D[0], which is an array of integers, and does decay to int *.
For your second case, arr is an array, but arr[i] is an int, since it is just one position in the array. The ampersand operator makes a pointer of what it operates, so &arr[i] is a pointer, and the call works.

Following a pointer in C

I will show the entire code, but look for the quotes above the pointers as I will be talking about my problem there. I will tell you what I think happened there at the quote comments. The code compiles and runs, I just need help understanding parts of the code.
#include <stdio.h>
#include <stdlib.h>
int *get_data(int num_grades);
float calc_average(int num_grades, int grades[]);
void display_average(float ave);
int main()
{
int num_grades = 10;
const int MAX_GRADE = 100;
Below this quote box at: int *result = get_data(num_grades);
I have a pretty simple understanding of pointers at this point, as I've been introduced to them recently, however I can't seem to wrap my head around what happens when you assign a function to a pointer. What I think should happen is that the pointer int *result should be pointing at an address. Instead its pointing to a function that is also a pointer i think. So is this a pointer to a pointer at: int *result = get_data(num_grades); ?
I will put the rest of my question at the get_data function below.
int *result = get_data(num_grades);
^ Above ^
if (num_grades ==0)
printf("no grades to average\n");
else
{
float ave = calc_average(num_grades, result);
display_average(ave);
}
free(result);
return 0;
}
float calc_average(int num_grades, int grades[])
{
float ave;
int i;
int sum = 0;
for (i = 0; i < num_grades; i++)
{
sum+=grades[i];
}
ave = (float)sum/num_grades;
return ave;
}
void display_average(float ave)
{
printf("average: %.2f\n", ave);
}
Below this quote box,
I think this is a function pointer that returns a int pointer?
So, inside the body of the function, we create a new pointer, allocate memory for it, assign grades for each 'pointee' i think, and then I'm not sure why a[i] = grade is working, what are these indexes coming from, I don't understand why this is working if there is no array declared. Can someone explain what is happening here? How does this work? I'm really confused here.
int *get_data(int num_grades)
{
int* a;
a = malloc(num_grades * sizeof(int));
int i;
for (i = 0; i < num_grades; i++)
{
printf("enter a grade: ");
int grade;
scanf("%d", &grade);
if(grade<=100)
{
a[i] = grade;
}
else
{
printf("grade needs to be > 0 and <= 100\n");
i--;
}
}
return a;
^ Above, this whole function ^
}
get_data is a function which returns a pointer to an integer. First of all:
int *result = get_data(num_grades);
in this line you are not assigning to result a pointer to function, but the result of the function being called with num_grades as argument. That is to say, to the a you calculated in the body of get_data. And after that:
int *get_data(int num_grades)
this is the declaration of a function called get_data which takes one int parameter and returns a pointer to int. You could rearrange the spaces like this:
int* get_data(int num_grades)
if it makes things clearer. In this context, saying that get_data is a pointer to function would not even make sense, since it's immediately followed by its body. For reference:
int (*get_data)(int num_grades);
this is how the declaration of a pointer to function taking one int param and returning an int looks like. And there can't be a function body after it.
... however I can't seem to wrap my head around what happens when you assign a function to a pointer.
You aren't assigning a function to a pointer; you're assigning the return value of the function (which happens to be an int * value) to a variable which happens to store int * values.
So is this a pointer to a pointer at: int *result = get_data(num_grades); ?
No. int * means 'pointer to int'.
I think this is a function pointer that returns a int pointer?
No. The function returns an int * (pointer to int). There is a function pointer in your code, though that isn't a function (because it's a function pointer) and it doesn't return anything (because it's not a function; it's a function pointer).
Remember, int * means 'pointer to int'.
and then I'm not sure why a[i] = grade is working, what are these indexes coming from, I don't understand why this is working if there is no array declared. Can someone explain what is happening here? How does this work? I'm really confused here.
The array[index] operator is actually a pointer[index] operator. It's syntactic sugar for *(array + index) or *(pointer + index).
Whenever an expression that has an array type is used (with the exception being taking the sizeof or &addressof an array), the expression is converted to a pointer. The pointer points to the first item of the array...
So whilst your pointer declaration will have different semantics for the sizeof and &addressof operators, it'll have the same semantics for the 'array subscript' operator.
A similar concept applies to functions (hence the "function pointer" explanation above). Technically, in your expression int *result = get_data(num_grades); you're not applying the function(argument) operator; you're applying the function_pointer(argument) operator. The expression denoting the function is converted to a function pointer...

how to copy returned array directly into another array?

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.

Passing dynamically allocated array as a parameter in C

So... I have a dynamically allocated array on my main:
int main()
{
int *array;
int len;
array = (int *) malloc(len * sizeof(int));
...
return EXIT_SUCCESS;
}
I also wanna build a function that does something with this dynamically allocated array.
So far my function is:
void myFunction(int array[], ...)
{
array[position] = value;
}
If I declare it as:
void myFunction(int *array, ...);
Will I still be able to do:
array[position] = value;
Or I will have to do:
*array[position] = value;
...?
Also, if I am working with a dynamically allocated matrix, which one is the correct way to declare the function prototype:
void myFunction(int matrix[][], ...);
Or
void myFunction(int **matrix, ...);
...?
If I declare it as:
void myFunction(int *array, ...);
Will I still be able to do:
array[position] = value;
Yes - this is legal syntax.
Also, if I am working with a dynamically allocated matrix, which one
is correct to declare the function prototype:
void myFunction(int matrix[][], ...);
Or
void myFunction(int **matrix, ...);
...?
If you're working with more than one dimension, you'll have to declare the size of all but the first dimension in the function declaration, like so:
void myFunction(int matrix[][100], ...);
This syntax won't do what you think it does:
void myFunction(int **matrix, ...);
matrix[i][j] = ...
This declares a parameter named matrix that is a pointer to a pointer to int; attempting to dereference using matrix[i][j] will likely cause a segmentation fault.
This is one of the many difficulties of working with a multi-dimensional array in C.
Here is a helpful SO question addressing this topic:
Define a matrix and pass it to a function in C
Yes, please use array[position], even if the parameter type is int *array. The alternative you gave (*array[position]) is actually invalid in this case since the [] operator takes precedence over the * operator, making it equivalent to *(array[position]) which is trying to dereference the value of a[position], not it's address.
It gets a little more complicated for multi-dimensional arrays but you can do it:
int m = 10, n = 5;
int matrixOnStack[m][n];
matrixOnStack[0][0] = 0; // OK
matrixOnStack[m-1][n-1] = 0; // OK
// matrixOnStack[10][5] = 0; // Not OK. Compiler may not complain
// but nearby data structures might.
int (*matrixInHeap)[n] = malloc(sizeof(int[m][n]));
matrixInHeap[0][0] = 0; // OK
matrixInHeap[m-1][n-1] = 0; // OK
// matrixInHeap[10][5] = 0; // Not OK. coloring outside the lines again.
The way the matrixInHeap declaration should be interpreted is that the 'thing' pointed to by matrixInHeap is an array of n int values, so sizeof(*matrixInHeap) == n * sizeof(int), or the size of an entire row in the matrix. matrixInHeap[2][4] works because matrixInHeap[2] is advancing the address matrixInHeap by 2 * sizeof(*matrixInHeap), which skips two full rows of n integers, resulting in the address of the 3rd row, and then the final [4] selects the fifth element from the third row. (remember that array indices start at 0 and not 1)
You can use the same type when pointing to normal multidimensional c-arrays, (assuming you already know the size):
int (*matrixPointer)[n] = matrixOnStack || matrixInHeap;
Now lets say you want to have a function that takes one of these variably sized matrices as a parameter. When the variables were declared earlier the type had some information about the size (both dimensions in the stack example, and the last dimension n in the heap example). So the parameter type in the function definition is going to need that n value, which we can actually do, as long as we include it as a separate parameter, defining the function like this:
void fillWithZeros(int m, int n, int (*matrix)[n]) {
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
matrix[i][j] = 0;
}
If we don't need the m value inside the function, we could leave it out entirely, just as long as we keep n:
bool isZeroAtLocation(int n, int (*matrix)[n], int i, int j) {
return matrix[i][j] == 0;
}
And then we just include the size when calling the functions:
fillWithZeros(m, n, matrixPointer);
assert(isZeroAtLocation(n, matrixPointer, 0, 0));
It may feel a little like we're doing the compilers work for it, especially in cases where we don't use n inside the function body at all (or only as a parameter to similar functions), but at least it works.
One last point regarding readability: using malloc(sizeof(int[len])) is equivalent to malloc(len * sizeof(int)) (and anybody who tells you otherwise doesn't understand structure padding in c) but the first way of writing it makes it obvious to the reader that we are talking about an array. The same goes for malloc(sizeof(int[m][n])) and malloc(m * n * sizeof(int)).
Will I still be able to do:
array[position] = value;
Yes, because the index operator p[i] is 100% identical to *(ptr + i). You can in fact write 5[array] instead of array[5] and it will still work. In C arrays are actually just pointers. The only thing that makes an array definition different from a pointer is, that if you take a sizeof of a "true" array identifier, it gives you the actual storage size allocates, while taking the sizeof of a pointer will just give you the size of the pointer, which is usually the system's integer size (can be different though).
Also, if I am working with a dynamically allocated matrix, which one is the correct way to declare the function prototype: (…)
Neither of them because those are arrays of pointers to arrays, which can be non-contigous. For performance reasons you want matrices to be contiguous. So you just write
void foo(int matrix[])
and internally calculate the right offset, like
matrix[width*j + i]
Note that writing this using the bracket syntax looks weird. Also take note that if you take the sizeof of an pointer or an "array of unspecified length" function parameter you'll get the size of a pointer.
No, you'd just keep using array[position] = value.
In the end, there's no real difference whether you're declaring a parameter as int *something or int something[]. Both will work, because an array definition is just some hidden pointer math.
However, there's is one difference regarding how code can be understood:
int array[] always denotes an array (it might be just one element long though).
int *pointer however could be a pointer to a single integer or a whole array of integers.
As far as addressing/representation goes: pointer == array == &array[0]
If you're working with multiple dimensions, things are a little bit different, because C forces you declare the last dimension, if you're defining multidimensional arrays explicitly:
int **myStuff1; // valid
int *myStuff2[]; // valid
int myStuff3[][]; // invalid
int myStuff4[][5]; // valid

Resources