Arrays & pointers in C - c

So I have the following code snippet:
#include <stdio.h>
void pointer_shift(int *a, int n);
int main(void) {
int a[] = {100, 101, 102};
pointer_shift(a1, 3);
}
void pointer_shift(int *a, int n) {
int i;
for (i = 0; i != n - 1; i++) {
*(a + i) = *(a + i + 1);
}
}
I just want to clarify how the pointers work in this snippet. So pointer_shift takes in 'a', a pointer to an int, correct? a1 is passed in to this parameter, and since arrays decay to a pointer to their first element, it works.
First of all, hopefully what I said in the above paragraph is correct. Secondly, what does *(a + i) = *(a + i + 1); actually do? Say we're on the first iteration of the for loop, and i = 0. Then the left side, *a, accesses what, exactly? Does it represent a pointer? I thought * was the dereferencing operator, and accesses the object that a pointer points to... And so then it sets *a = *(a + 1). (a + 1) is the next element in the array, but what exactly does this assignment do, and why?
Thanks!

It is actually not pointer shift, but value shift, *(a+i) is of same effect as a[i], so what it does is a[i] = a[i+1]

*(a + i) = *(a + i + 1); is copying array elements within the array using a bit of pointer arithmetic.
*(a + i) is equivalent to a[i], so the statement is equivalent to a[i] = a[i + 1];. The loop is moving the array values "to the left" in the array: a[0] = a[1]; a[1] = a[2]; and so on.
Your understanding of the function call is correct.

I just want to clarify how the pointers work in this snippet. So pointer_shift takes in 'a', a pointer to an int, correct? a1 is passed in to this parameter, and since arrays decay to a pointer to their first element, it works.
Yes, when you pass an array to a function it degrades to a pointer. An array is not a pointer in an object sense, but it is a pointer in a value sense. When you pass it to a function its value is passed, i.e., a pointer to the first element.
array indexing is the same as pointer arithmetic, so the last two lines in this snippet are equivalent:
int arr[] = {1, 2, 3};
arr[0] = 10;
*arr = 10;
as are these:
arr[1] = 20;
*(arr + 1) = 20;

The expression a + i is pointer arithmetic, incrementing the memory address stored in a by i units of the pointer size of a. So if a pointer to an int takes four bytes on your system, and if the current memory address is, say, 0x1234 the value of a + 1 would be 0x1238.
What the asterisk does is dereference that address and access the actual value at that address. If you have 100 stored at a or a[0], and 101 stored at a + 1 or a[1], then *(a + i) = *(a + i + 1) replaces 100 with 101 at a[0], for i = 0.
Basically, you want to read this C tutorial on pointers and arrays.

Related

Writing array reference using pointer arithmetic

let consider the following fragment of Code:
#include<stdio.h>
main()
{
int count[100][10];
*(count + (44*10)+8)=99;
printf("%d",count[44][8]);
}
What is the wrong with it?
Array-to-pointer decay only works for one level; so int count[100][10]; decays to int (*)[100] (Why does int*[] decay into int** but not int[][]?).
You can either cast count to int* or use &count[0][0] to get an int* pointer to the first element of the 2D array.
count[44][8]
is not initialized and you are trying to print the value of it which is UB.
a[i][j] = *(a[i] + j);
a[i][j] = *(*(a+i) + j);
So if you want to initialize count[44][8] then do
*(count[44] + 8) = 10; /* or *(*(count + 44) + 8) = 10 */
printf("%d",count[44][8]);
*(count + (44*10)+8)=99; should be
*(count[0] + (44*10)+8)=99;
Type of countp[0] can be reinterpreted as int * as you want.
Live code here
Type of count is int [100][10] so adding some big number to it would go 10 times ahead as you want and access to that location would lead to UB.
Anopter way to write the same is:
*( *(count + 44) + 8 )=99;

Using pointers to get value from multidimensional array - C

I am trying to get value from "second row" in multidimensional array. But I have some problems with that.
I thought that numbers are stored sequentialy in memory so tab[2][2] is stored same as tab[4]. But it seems that I was wrong.
This is what I tried:
int b[2][2] = {{111,222},{333,444}};
int i = 0;
for(;i < 100; i++)
printf("%d \n", **(b+i));
The problem is that I get only 111 and 333 as the result. There is no 222 or 444 in other 98 results. Why?
The problem is that **(b+i) doesn't do what you think it does. It evaluates to:
b[i][0]
As Matt McNabb noted,
**(b+i)
is equivalent to:
*(*(b+i)+0)
and since *(b+i) is equivalent to b[i], the expression as a whole can be seen as:
*(b[i]+0)
and hence:
b[i][0]
Since your array has only 2 rows, only the values of i for 0 and 1 are in bounds of the array (that's the 111 and 333). The rest was wildly out of bounds.
What you could do is:
#include <stdio.h>
int main(void)
{
int b[2][2] = { { 111, 222 }, { 333, 444 } };
int *base = &b[0][0];
for (int i = 0; i < 4; i++)
printf("%d: %d\n", i, base[i]);
return 0;
}
Output:
0: 111
1: 222
2: 333
3: 444
You can think of a two-dimensional array as a special form of a one-dimensional array. Your array holds 2 elements (!). (Each element happens to be an array of two elements, but let's ignore that for a sec.) Let's make the dimensions different so that we can distinguish them:
int arr2d[2][3] holds 2 elements (each being an array of 3 elements). The "primary index" is written first, that is if you have a one-dimensional array of 3 like int arr1d[3]and want to have an array of those with three elements like arr2d, you have to write arr2d[2][3]. You could arrange that with a typedef which makes it clear that all arrays in C are essentially 1-dimensional:
typedef int arr3IntT[3];
arr3IntT arr2d[2] = { {0,1,2}, {3,4,5} };
Now what does arr2d+i mean? arr2d, like any array, decays to a pointer to its first element (which is an array of 3 ints). arr2d+1 adds the offset of 1 of those elements to the address, so that like always the expression yields the address of the second element (which is the second array of 3 ints). Dereferencing it once like *(arr2d+1) yields that element, i.e. the one-dimensional sub-array of 3 ints. It decays to a pointer to its first element, i.e. a pointer to the first int in that second sub-array. Dereferencing that in the expression **(arr2d+1) yields that int, like always. To summarize: In your original code you iterate from sub-array to sub-array, always referencing the first of their elements, incidentally going out of bounds for i>1.
But principally you are right, elements of n-dimensional arrays in C are lying contiguously in memory, so you can access them one by one if you like to. You just have to index a pointer to int, not one to int[3]. Here is how: The expression arr2d decays to a pointer to its first element which is an array of 3 ints. Dereferencing that gives that first element, a one-dimensional array of 3 ints. Like all arrays, it decays to a pointer to its first element, an int, which is the very first element in the data:
#include<stdio.h>
int main()
{
int arr2d[2][3] = { {0,1,2}, {3,4,5} };
int *p_el1 = *arr2d;
int i, j;
// Sanity check by indexing 2-dimensionally
for(i=0; i<2; i++) for(j=0; j<3; j++) printf("%d\n", arr2d[i][j]);
// iterate the elements 1 by 1
for(i=0; i<3*2; i++) printf("%d\n", p_el1[i]);
}
A multidimensional array is not a fundamentally new type. It's an array type where the elements are themselves arrays. To quote the C99 standard §6.2.5 ¶20 (Types)
An array type describes a contiguously allocated nonempty set of
objects with a particular member object type, called the element type.
Array types are characterized by their element type and by the number
of elements in the array.
int b[2][2] = {{111, 222}, {333, 444}};
The above statement defines b to be an array of 2 elements where each element is the type int[2] - an array of 2 integers. It also initializes the array with the array initializer list. An array is implicitly converted to a pointer to its first element in some cases.
In the printf call, b decays to a pointer to its first element. Therefore, it's equivalent to &b[0] and has type int (*)[2] - a pointer to an array of 2 integers. Please note that it's undefined behaviour to access elements out of the bound of an array. Therefore, the for loop condition i < 100 is wrong. It should be i < 2. Now, let's try to demystify the expression **(b+i).
b -------------> pointer to a[0]
b + i ---------> pointer to a[i]
*(b + i) -----> a[i]
*(*(b + i)) ---> *(a[i]) ----> *(&(a[i])[0]) ----> a[i][0]
As noted, the elements of the array are themselves arrays. Therefore, a[i] is an array. Again, the array decays to a pointer to its first element, i.e., to &(a[i])[0]. Applying indirection operator * on this pointer gets us the value at that address which is a[i][0].
You can access the elements of the array through a pointer but the pointer type must be a pointer to element type of the array.
#include <stdio.h>
int main(void) {
int b[2][2] = {{111, 222}, {333, 444}};
int (*p)[2] = b;
// (sizeof b / sizeof b[0]) evaluates to
// the size of the array b
for(int i = 0; i < (sizeof b / sizeof b[0]); i++)
// (sizeof *p / sizeof (*p)[0]) evaluates to
// the size of element of the array which is
// itself an array.
for(int j = 0; j < (sizeof *p / sizeof (*p)[0]); j++)
printf("%d\n", *(*(p + i) + j));
return 0;
}
Here, the expression *(*(p + i) + j) can be decoded as
p ---------------> pointer to the first element of b, i.e., &b[0]
(p + i) ----------> pointer to b[i], i.e., &b[i]
*(p + i) ---------> the array element b[i] ---> decays to &(b[i])[0]
*(p + i) + j -----> &(b[i])[j]
*(*(p + i) + j) --> the element b[i][j]
Therefore, the expression *(*(p + i) + j) is equivalent to b[i][j]. In fact, the C99 standard §6.5.2.1 ¶2 says -
The definition of the subscript operator [] is that E1[E2] is
identical to (*((E1)+(E2)))
This means we have the following are equivalent with context to the above program -
*(*(p + i) + j)
// equivalent to
p[i][j]
// equivalent to
b[i][j]
// equivalent to
*(*(b + i) + j)

Arrays and pointers in C

I have this piece of program and there are some parts that I don't understand...
‪#‎include‬ <stdio.h>
void increment( int *ptr) {++*ptr; }
int main(){
int a[] = { 5, 10 }, i = 0; // We have: vector a=[5,10] | i=0
increment(a); //This is the same as increment(&a) isn't it?
//So we have: a=[6,10] | i=0
increment(&i); // We increment i so: a=[6,10] | i=1
increment(&a[i]); //We increment the element at the position a[1]: a=[6,11] | i=1
increment(a+i); //OMG! What does it mean? a is an array isn't it? Then how can we
//make "a+1"? and how is this an address?
printf("\nResult: i= %d\n", i);
printf( "a[0] = %d\n" "a[1] = %d\n", a[0], a[1]);
return 0;
}
The printfs return:
i=1
a[0]=6
a[1]=12
How can this be explained?
When you pass an array to a function, the array decays to a pointer to the first element. So in the function, doing e.g. *ptr is dereferencing the first element in the array.
Also, because arrays decays to pointers, doing e.g. a[i] is equal to *(a + i).
Unrelated side-note: Because of the commutative of addition, the expression *(a + i) can be written as *(i + a) which leads to i[a] actually being a valid expression.
Arrays and pointer arithmetic are the same in C. If you've not come across pointer arithmetic here's a tutorial on it:
C Pointer Arithemtic
In essence:
a[3]
is the same as
*(a + 3)
Where a is a pointer.
When we give the name of array in the function call, the address of the arrya's first element is passed
ie; increment(a); is same as increment(&a[0]);
So while giving
incrementa(a+i);
since i and array a[] are both integers effectively that becomes
incrementa ( base address of array a (ie; &a[0]) + value of i )
i just acts as the offset to that array element
That it becomes the address of the second element which is &a[1]
so the 11 is modified to 12 while incrementing the value by the function

Pointer function with an array

I have a problem, I have a function and I do not understand a specific thing. The function is:
int F( int* x , int n ){
int i , m=0
for (i=0;i<n; i++){
m=x[ i ] + m;
}
return m * m ;
}
I call the function with a pointer and with an integer. Later I do a "for", but I do not understand the line:
m=x[ i ] + m;
Because x is a pointer not an array.
Could you please help me.
Then x points to the memory position then to +1. For example if i call the function with
n=10
x=&n
F(x,n)
the function returns somenthing strange.
X points to the position memory to n, later to the position memory to n+1??
Since x is a pointer, when you pass the array to the function, x points to the first element of the array. Since array is a contigous allocation of memory, The pointer can be made to point to consecutive elements of the array. Thats why
m=x[i]+m
x[i] implies to the ith index from the first element of the array
main()
{
int x[10]={1,2,3,4,5,6,7,8,9,10},sum;
sum=function(x,10);
return 0;
}
This function sends the array to the function, with 10, the size of the array
Arrays are represented as contiguous memory and the array variable gets interpreted as a pointer to the base of that memory (e.g. &(x[0])). Array offset syntax gets translated into pointer arithmetic.
See this post, which clarifies the difference between pointer and arrays:
[] - indexed dereference
a[b] is equivalent to *(a + b). This means a and b must be a pointer to an array element and an integer; not necessarily respectively, because a[b] == *(a + b) == *(b + a) == b[a]. Another important equivalence is p[0] == 0[p] == *p.
The function might be equivalently declared (with more clarity perhaps):
int F(int x[], int n);
and you would call it like so:
int data[3] = {1, 2, 3};
int value = F(data, 3);

Matrix Access Ansi C

Why the last printf in the main function doesn't print to the screen the value 10?
I know that in ANSI C, statically allocated matrix are arranged in memory in this way:
matrix: matrix[0][0], matrix[0][1],...,matrix[0][ColumnsDimension-1],matrix[1][0], etc
#include <stdio.h>
#include <stdlib.h>
#define dimRighe 20
#define dimColonne 30
int main()
{
int matrice[dimRighe][dimColonne];
int i,j;
for(i=0;i<dimRighe;i++)
for(j=0;j<dimColonne;j++)
matrice[i][j] = i+j;
matrice[0][3] = 10;
i = 0; j = 3;
printf("%d",*matrice[i*dimColonne+j]);
return 0;
}
Use *(matrice[i * dimColonne] + j) instead.
Why the last printf in the main function doesn't print to the screen the value 10?
Because matrice is an array of arrays ...
and matrice[whatever] is an array (which in most circunstances "decays" to a pointer to its first element)
and *matrice[whatever] is the contents of the first element of the array matrice[whatever].
In your code you have:
matrice[i*dimColonne+j]
Since i is 0 this evaluates to
matrice[j]
Since j is 3 this means
matrice[3]
When you print *matrice[3] that is equivalent to printing matrice[3][0] because matrice[3] is an array. And an array decays to a pointer to its first element.
But you don't want to do it this way at all. You should simply write matrice[i][j] and let the compiler do the work.
Change
printf("%d",*matrice[i*dimColonne+j]);
to simply be
printf("%d", matrice[i][j]);
if all you're worred about is printing out the right value. After all, that's how you assigned it.
If you're doing this as an exercise to understand how array subscripting works, then there are several things you need to remember.
First, except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be replaced with ("decay to") an expression of type "pointer to T", and its value will be the address of the first element of the array. The expression matrice is an array expression of type "20-element array of 30-element array of int"; in most circumstances, it will be converted to an expression of type "pointer to 30-element array of int", or int (*)[30]. Similarly, the expression matrice[i] is an expression of type "30-element array of int", and in most cirumstances it will be converted to an expression of type "pointer to int", or int *.
Here's a handy table to remember all of this:
Declaration: T a[N];
Expression Type Decays to
---------- ---- ---------
a T [N] T *
&a T (*)[N]
*a T
a[i] T
Declaration: T a[M][N];
Expression Type Decays to
---------- ---- ---------
a T [M][N] T (*)[N]
&a T (*)[M][N]
*a T [N] T *
a[i] T [N] T *
&a[i] T (*)[N]
*a[i] T
a[i][j] T
Second, the subscripting operation a[i] is defined as *(a + i); that is, you compute an address based on i number of elements (NOT BYTES) from the base address of your array and dereference the result. For example, if a is an array of int, then *(a + i) will give you the value of the i'th integer after a. If an is an array of struct foo, then *(a + i) will give you the value of the i'th struct after a. Pointer arithemtic always takes the size of the base type into account, so you don't need to worry about the number of bytes in the offset.
The same logic applies to multidimensional arrays, you just apply the rule recursively for each dimension:
a[i][j] == *(a[i] + j) == *(*(a + i) + j)
a[i][j][k] == *(a[i][j]+ k) == *(*(a[i] + j) + k) == *(*(*(a + i) + j) + k)
Note that you should almost never have to do these dereferences manually; a compiler knows what an array access looks like and can optimize code accordingly. Under the right circumstances, writing out the dereferences manually can result in slower code than using the subscript operator.
You can index into a 2-d array as if it were a 1-d array like so:
a[i*rows + j] = val;
but I wouldn't (the types of the expressions don't match up cleanly). Note that you multiply i by the number of rows, not columns.
You could also print it like this:
char *matrixAsByteArray = (char *) matrice;
char *startIntAddr = matrixAsByteArray + i * dimColonne * sizeof(int) + j * sizeof(int);
int outInt = *startIntAddr | *(startIntAddr + 1) << 8 | *(startIntAddr + 2) << 16 | *(startIntAddr + 3) << 24;
printf("%d", outInt);
What this does is first, it converts your matrix to an array of bytes, then, it gets the starting address of the integer you need, and then it reconstructs the integer from the first four bytes read from that address.
This is a bit overkill, but a fun solution to the problem.

Resources