increment of a pointer to the next array element [duplicate] - c

This question already has answers here:
Is it safe to keep a pointer out-of-bounds without dereferencing it? [duplicate]
(3 answers)
Closed last year.
Recently, I found an interesting code snippet about array and pointers I didn't understand as a whole.
Here's the code:
void Function(int *B, int *A, int *C, int m)
{
int i;
A++;
for(i = 0; i < m; i++, B++, A++, C++)
*C=*B + *(A-1);
}
int main()
{
int A[] = {3,6,2};
int B[] = {5,7,9};
int C[3];
int n = 3;
int i;
Function(A,B,C,n);
for(i = 0; i < n; i++)
printf("%d ",C[i]);
return 0;
}
Okay, so, in the main, we have two arrays, variable n which we're forwarding to the function. *B, *A, *C are pointers to the first element of an array.
First, we have A++, which means that now, A shows on the second element of an array, which is 7. In the first for loop, i = 0, then *C(first element) = 3 + 5 = 8
Then, i = 1, B is now pointing on 6, A on 9.
Next, the second for loop looks like this:
*C(second element) = 6 + 7 = 13
Till this part, i understood. Now, i incremented to 2, B is showing on 2, but then, we have A++ again, but how A will increment when there is no other element in that array, it's blank basically? When i debugged, in third for loop, A will be 9(A-1), but again, not completely sure how that work.

It's ok to increment a pointer to just past the last element in an array. With such a pointer, you can't dereference it or increment it again (it's undefined behavior).
C is very specific about what you can do with pointer arithmetic without causing undefined behavior, for example disallowing decrementing a pointer to before the first element of the array, or having the pointer increment after the array except for just after the final element. If you have a single object pointed to (rather than an array), it's treated as an array of length 1 for these rules.

Related

Why can't I return a int[] from my C function [duplicate]

This question already has answers here:
What does impossibility to return arrays actually mean in C?
(5 answers)
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 2 years ago.
I somehow can not return a int[] from my function I wrote in the code below. Can anybody explain why I am doing it wrong, instead of only posting a code solution .
Why can't I square all values and set arr = square_all(arr)?
#include <stdio.h>
void print(int arr[])
{
for(int i = 0; i <= sizeof(arr) / sizeof(int); i++)
{
printf("%i", arr[i]);
}
}
int* square_all(int arr[])
{
for(int i = 0; i <= sizeof(arr) / sizeof(int); i++)
{
arr[i] = arr[i] * arr[i];
}
return arr;
}
int main()
{
int arr[] = {1, 2, 3};
print(arr);
arr = square_all(arr);
return 0;
}
The problem isn't the returning, but rather the assignment to arr in the main function.
You can't assign to an array, only to its individual elements. You can also copy to an array.
However, in this case there's no need for an assignment (or a copy), since you modify the array in-place. So all you really need is:
square_all(arr); // No assignment
A larger problem is your use of sizeof in the functions. Because you don't pass an array to the functions, you pass a pointer. And the size of a pointer is the size of a pointer is the size of the actual pointer itself and not what it might point to.
See Why isn't the size of an array parameter the same as within main?
Furthermore, since array indexes are zero-based, an array of X elements will have indexes from 0 to X - 1, inclusive. That means a loop-condition like i <= X will include X as an index, and that's out of bounds. Use i < X as a loop condition instead.
My guess is that you misunderstood how arrays are passed to functions, that arrays are copied for the function calls, which they are not. A function argument declaration like int arr[] is actually translated by the compiler as int *arr. And when you call the function, you only pass a pointer to its first element (e.g. print(arr) is really equal to print(&arr[0])).

Passing pointers as argument in C functions

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.

What does dereferencing and printing the pointer a do in this situation? [duplicate]

This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 5 years ago.
I am running the following code:
int* range(int start, int end, int step){
int size = (end - start)/step;
int out[size];
for(int i = 0, j = start; i < size; i++, j += step){
out[i] = j;
}
return out;
}
int main()
{
int *a = range(1, 5, 1);
printf("%i\n", *a);
printf("%i\n", *a);
return 0;
}
I get 1 on the first line, as expected, and some garbage value on the second (6422260 for instance). What is the explanation? I would expect to get 1 on both lines.
If this:
int out[size];
doesn't appear in file scope (in other words, appears inside a function), it defines a variable with automatic storage duration. This means the variable only exists as long as execution is inside its scope (which is the nearest set of braces). Once the scope is left, the variable is gone.
Returning an array isn't possible in C, return out instead returns a pointer to the array's first element. So you see the problem: The pointer points to an object that doesn't exist any more.
Now with your code, the first call to printf() seems to work. This is "by accident" (it's not guaranteed at all), but can be explained: In your implementation, nothing changes the memory where your array was located, until another function (here printf()) is called and overwrites this memory with its own local variables.
How to do this correctly: There are several possibilities:
Let the caller provide the array.
return a pointer to an allocated array using malloc() as shown in anoher answer, caller has to free() it.
Add a static to the array definition, which gives it static storage duration (for the whole execution time of the program), but be aware of a severe consequence of this: there's only one instance of this array forever, creating all sorts of problems, so, better don't.
IMHO, 1. is the most idiomatic C way of doing this, using your original code:
void range(int *out, int start, int end, int step){
int size = (end - start)/step;
for(int i = 0, j = start; i < size; i++, j += step){
out[i] = j;
}
}
int main()
{
int a[5];
range(a, 1, 5, 1);
printf("%i\n", *a);
printf("%i\n", *a);
return 0;
}

Assigning pointer from two-dimensional array

#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int ar[2][2] = {1,2,3,4};
int **p= NULL , i=0, j=0;
p = ar; //compiler error. Confused ! Do i need to assign &a or anything.
puts("OUT: ");
for(i = 0; i < 2; i++)
{
for(j = 0 ; j < 2; j++)
{
printf("%2d", *(*(ar + i) + j));
printf("%2d", *(*(p + i) + j)); /* This is wrong . Compiler error */
}
}
exit(0);
}
I want to create a pointer to the 2D array so that instead of ar in the for loop
i should be able to put p. I'm confused. I know other methods of accessing 2d
elements but i'm confused with this example.
ar[2][2] will NOT decompose into pointer to pointer int **p=ar //is wrong,It will be decomposed into Pointer to first row(if we think in matrix form, which i think its easy),this means in your example your 2-d array consists of 2 rows,Each row has 2 integers(columns).
Hence ar will be decomposed into pointer to 2 integers, Which can be programmatically declared as
int (*p)[2]; //this is pointer to 2 ints
int (*p)[3]; //this is pointer to 3 ints,if your array was declared like this ar[2][3]
So in your program you need to change int **p=NULL to int (*p)[2];
When we say a pointer to 2 integers,it means that When you add one (ex:- p+1) for above example then this will point to the next two integers of 2-d array(which means next row).
In the first case you have an array of int[2], while in the second case you have an array of int*.
If you use sizeof(ar[0]), it would print 2*sizeof(int), while the second would print sizeof(int*).
printf("sizeof(ar) = %zu\n", sizeof(ar));
printf("sizeof(ar[0]) = %zu\n", sizeof(ar[0]));
printf("sizeof(ar[0][0]) = %zu\n", sizeof(ar[0][0]));
printf("sizeof(p) = %zu\n", sizeof(p));
printf("sizeof(*p) = %zu\n", sizeof(*p));
printf("sizeof(**p) = %zu\n", sizeof(**p));
Since I tried you code, replaced p = a with p = ar I only have these errors:
$ gcc -Wall foobar.c
foobar.c: In function ‘main’:
foobar.c:6:3: warning: missing braces around initializer [-Wmissing-braces]
foobar.c:6:3: warning: (near initialization for ‘ar[0]’) [-Wmissing-braces]
foobar.c:12:5: warning: assignment from incompatible pointer type [enabled by default]
foobar.c:21:7: warning: too many arguments for format [-Wformat-extra-args]
And it fails too:
$ ./a.out
sizeof(ar) = 16
sizeof(ar[0]) = 8
sizeof(ar[0][0]) = 4
sizeof(p) = 8
sizeof(*p) = 8
sizeof(**p) = 4
OUT:
Segmentation fault
Which is normal, assuming p is not so well defined.
a quote from comp.lang.c FAQ list, Question 6.18
The rule (see question 6.3) by which arrays decay into pointers is not
applied recursively. (Once the rule has been applied once, the result
is a pointer to which the rule no longer applies.) An array of arrays
(i.e. a two-dimensional array in C) decays into a pointer to an array,
not a pointer to a pointer.
int ** and int [2][2] are not compatible. you should think of your ar array as of an array that holds another arrays. multidimensional arrays allocated on stack are stored in memory continguously.
statement int ar[2][2] will be changed by the compiler to int (*ar)[2]. notice the placement of parentheses. this is because of operators precedence:
() operator has higher precendece than [] operator
[] operator has higher precedence than * operator.
. so if you would omit them, then:
int *ar[2]; // ar is an array of length 2 that holds pointers to ints.
int (*ar)[2]; // ar is a pointer to array of length 2 that hold ints.
you can resolve your problem by:
changing int **p = NULL; to int (*p)[2];
changing int ar[2][2] to int **ar and then properly allocate memory for rows and columns using malloc()
think of how that 2d array is subscripted. for example, the statement:
printf("%2d ", *(*(ar + 1) + 1)); // print the ar[1][1]
adds 1 to ar pointer, which points to int [2]. 8 bytes are added to the address of beginning of array, then after dereference adding 1 will add only 4 bytes, since it refers now to int.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main(void)
{
const int row=4, col=4;
int ar[row][col] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
int **p= NULL ;
int *np = &ar[0][0];
p = &np;
for(int i = 0; i < row; i++)
{
for(int j = 0 ; j < col; j++)
{
printf("address of a[%d][%d] is %x\n",i,j,&ar[i][j]);
printf("%2d\n", *(*(ar + i) + j));
printf("%2d\n", *(*(p)+ i*col + j));
}
}
_getch();
exit(0);
}
i tried like this, it worked for me.

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