The sum of array elements using pointer in C - c

#include <stdio.h>
int main() {
int a[] = { 5, 5, 8, 34, 12, 2 };
int *p;
int i = 0, c = 0;
int sum = 0;
for(p = &a[i]; i < sizeof(a) / sizeof(a[0]); i++) {
sum += *p;
}
printf("the sum is %d\n", sum);
}
I tried to find the sum of array elements using pointer, but the result is not correct. The value of i does seem to increment, but it is not observed in the expression a[i]. I want to know why incrementing i is not having an effect on indexing the array a.

In this for loop
for(p=&a[i];i<sizeof(a)/sizeof(a[0]);i++){
sum+= *p;
}
the pointer p always points to the first element of the array because the pointer is initialized only once p=&a[i] when i is equal to 0 and is not being changed within the for loop.
If you want to use a pointer to access elements of the array in the for loop then the variable i is redundant. Instead write
int a[] = { 5, 5, 8, 34, 12, 2 };
const size_t N = sizeof( a ) / sizeof( *a );
int sum = 0;
for ( const int *p = a; p != a + N; ++p ){
sum += *p;
}
printf( "the sum is %d\n",sum );
Pay attention to that in this declaration within the for statement
const int *p = a;
the array designator a is implicitly converted to pointer to its first element. So it is enough to write as shown above instead of
const int *p = &a[0];

If you want to use pointers, then you need to get rid of the residue from your earlier code which used the subscript operator.
Here p points at &a[0] (a alone decays into an int* here so no need to write out &a[0]) and end points at one element beyond the last element. The iteration should therefore stop when p == end.
#include <stdio.h>
int main(void) {
int a[] = {5, 5, 8, 34, 12, 2};
int sum = 0;
for (int *p = a, *end = a + sizeof a / sizeof *a; p != end; ++p) {
sum += *p;
}
printf("the sum is %d\n", sum);
}

Related

Pointer initialization/dereferencing

What is the difference between
int(*a)[5];
int b[5] = { 1, 2, 3, 4, 5 };
i = 0;
a = &b;
for (i = 0; i < 5; i++)
printf("%d\n", *(*a+i));
and
int b[5] = { 1, 2, 3, 4, 5 };
int *y = b;
for (i = 0; i < 5; i++)
printf("%d\n", *y+i);
Both snippets produce same output but I dont understand what is the difference in initialization?
How is
int *y = b;
different to
int(*a)[5];
How to explain this kind of dereferencing?
printf("%d\n", *(*a+i));
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
In your second code snippet
int b[5] = { 1, 2, 3, 4, 5 };
int *y = b;
in the declaration of the pointer y the array designator b used as an initializer is implicitly converted to pointer to its first element. The above declaration is equivalent to
int *y = &b[0];
Dereferencing the pointer y you will get the first element of the array of the type int.
Try the following demonstration program.
#include <stdio.h>
int main( void )
{
int b[5] = { 1, 2, 3, 4, 5 };
int *y = b;
printf( "sizeof( *y ) = %zu, *y = %d\n", sizeof( *y ), *y );
}
Its output might look like
sizeof( *y ) = 4, *y = 1
Thus in this for loop
for (i = 0; i < 5; i++)
printf("%d\n", *y+i);
you just outputting the value of the first element of the array b plus the value of the variable i. That is actually the loop does not output elements of the array b because they even are not accessed except the first element of the array..
If you want to output elements of the array you need to write
for (i = 0; i < 5; i++)
printf("%d\n", *( y+i ));
It is the same as to write
for (i = 0; i < 5; i++)
printf("%d\n", y[i] );
because the subscript operator is evaluated like (the C Standard, 6.5.2.1 Array subscripting)
2 A postfix expression followed by an expression in square brackets []
is a subscripted designation of an element of an array object. The
definition of the subscript operator [] is that E1[E2] is identical to
(*((E1)+(E2))). Because of the conversion rules that apply to the
binary + operator, if E1 is an array object (equivalently, a pointer
to the initial element of an array object) and E2 is an integer,
E1[E2] designates the E2-th element of E1 (counting from zero).
In your first code snippet
int(*a)[5];
int b[5] = { 1, 2, 3, 4, 5 };
i = 0;
a = &b;
for (i = 0; i < 5; i++)
printf("%d\n", *(*a+i));
the pointer a is declared as a pointer to array of the type int[5]. So dereferencing the pointer you get an array of the type int[5].
Consider the following demonstration program,
#include <stdio.h>
int main( void )
{
int(*a)[5];
int b[5] = { 1, 2, 3, 4, 5 };
printf( "sizeof( *a ) = %zu\n", sizeof( *a ) );
}
Its output might look like
sizeof( *a ) = 20
In this for loop
for (i = 0; i < 5; i++)
printf("%d\n", *(*a+i));
the expression *a yields the pointed array b that used in the expression *a + i is converted to pointer to its first element. To make it clear you could rewrite the for loop the following way
for (i = 0; i < 5; i++)
{
int *p = *a;
printf("%d\n", *(p + i));
}
That is in this declaration
int *p = *a;
the array obtained by dereferencing the pointer a is implicitly converted to pointer to its first element according to the first provided quote from the C Standard..
Consider one more example. Let's assume that you have a two-dimensional array like for example
int b[2][5] =
{
{ 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 }
};
As it was pointed out above the array used in expressions with rare exception is converted to pointer to its initial (first) element.
The type of elements of the array is int[5]. So you can declare a pointer like
int ( *a )[5] = b;
In this case to output the array you can write for example
for ( int i = 0; i < 2; i++ )
{
for ( int j = 0; j < 5; j++ )
{
printf( "%d\n", *( *a + j ) );
}
++a;
}
After this statement
++a;
the pointer a will point to the second element of the array b that is to its second "row" of the type int[5] due to the pointer arithmetic..
And again this declaration
int ( *a )[5] = b;
is equivalent to
int ( *a )[5] = &b[0];
Almost a side note, but some of the code is incorrect.
Referring to the code below ...
Note that the first snippet, which I'll call foo is correct.
But, the second snippet which I'll call bar is incorrect. It only works [serendipitously] because the b array is 1, 2, 3, 4, 5 (i.e. in sorted order).
If the b array is not sorted, then bar will not print the correct order. This is because *y + i must be *(y + i)
For *y + i, the value fetched for all loop iterations is b[0] to which we add the value of i. To use array/index syntax, we are doing: y[0] + i
What we want is to fetch: b[0] b[1] ... b[4]
The corrected version is in baz. So, we use *(y + i). In array/index syntax, this is y[i].
Here is the code that illustrates this:
#include <stdio.h>
#if SORTED
int b[5] = { 1, 2, 3, 4, 5 };
#else
int b[5] = { 5, 4, 1, 2, 3 };
#endif
void
foo(void)
{
int (*a)[5];
a = &b;
printf("\n");
for (int i = 0; i < 5; i++)
printf("foo: %d\n", *(*a + i));
}
void
bar(void)
{
int *y = b;
printf("\n");
// NOTE/BUG: "*y + i" is incorrect -- see baz
for (int i = 0; i < 5; i++)
printf("bar: %d\n", *y + i);
}
void
baz(void)
{
int *y = b;
printf("\n");
// NOTE/FIX: correct fix for bar
for (int i = 0; i < 5; i++)
printf("baz: %d\n", *(y + i));
}
int
main(void)
{
foo();
bar();
baz();
return 0;
}
Here is the program output:
foo: 5
foo: 4
foo: 1
foo: 2
foo: 3
bar: 5
bar: 6
bar: 7
bar: 8
bar: 9
baz: 5
baz: 4
baz: 1
baz: 2
baz: 3

C pointer argument assigned to a parameter with a different value

I was trying to write a seemingly trivial function in C to get the maximum value in an array of integers. I'm trying to do so using pointers to get a better understanding. (I know how to do this passing the size of the array, the question is not how to do this another way)
#include <stdio.h>
int gimme_largest(int *, int *);
int main(void)
{
int arr[] = {1, 22, 3, 44, 5};
int largest;
printf("In main, arr:\t\t\t %p \n", arr);
printf("In main, arr + sizeof(arr):\t %p\n", arr + 5);
putchar('\n');
largest = gimme_largest(arr, arr + sizeof(arr));
// printf("\n\nThe largest is %d", largest);
return 0;
}
int gimme_largest(int *a, int *lastPlusOne)
{
int largest = *a; // let's assume the first element is the largest one
printf("In gimme_largest, a:\t\t %p\n", a);
printf("In gimme_largest, a + 5:\t %p\n", a + 5);
printf("In gimme_largest, lastPlusOne:\t %p\n", lastPlusOne);
while (a < lastPlusOne) {
if (*a > largest)
largest = *a;
a++;
}
return largest;
}
The problem is that lastPlusOne does not equal a + 5 in the invoked function, but a higher address; can't see why that's happening.
This call
largest = gimme_largest(arr, arr + sizeof(arr));
is invalid. sizeof( arr ) in the case of your program is equal to 5 * sizeof( int ) while for the correct pointer arithmetic you need to use only the number of elements in the array.
That is there shall be
largest = gimme_largest(arr, arr + sizeof(arr) / sizeof( *arr ) );
Thus the expression sizeof(arr) / sizeof( *arr ) is equal to the value 5 that you are using in this call of printf
printf("In main, arr + sizeof(arr):\t %p\n", arr + 5);
Pay attention to that the user can call the function with an empty range when a is equal to lastPlusOne. In this case the function will have undefined behavior because for an empty range there is no largest elemenet.
The function should return a pointer to the largest element.
Also as in C there is no function overloading then the function should be called for constant and non-constant arrays.
Here is a demonstrative program that shows how the functipon can be defined.
#include <stdio.h>
int * gimme_largest( const int *first, const int *last )
{
const int *largest = first;
if ( first != last )
{
while ( ++first != last )
{
if ( *largest < *first ) largest = first;
}
}
return ( int * )largest;
}
int main(void)
{
int arr[] = {1, 22, 3, 44, 5};
const size_t N = sizeof( arr ) / sizeof( *arr );
int *largest = gimme_largest( arr, arr + N );
printf( "The largest number is %d\n", *largest );
return 0;
}
The program output is
The largest number is 44
To get the end address of the array, you can do this by arr + sizeof(arr) / sizeof(arr[0]):
#include <stdio.h>
int gimme_largest(int *, int *);
int main(void)
{
int arr[] = {1, 22, 3, 44, 5};
int largest;
printf("In main, arr:\t\t\t %p \n", arr);
printf("In main, arr + sizeof(arr):\t %p\n", arr + 5);
putchar('\n');
largest = gimme_largest(arr, arr + sizeof(arr) / sizeof(arr[0]));
printf("\n\nThe largest is %d", largest);
return 0;
}
int gimme_largest(int *a, int *lastPlusOne)
{
int largest = *a; // let's assume the first element is the largest one
printf("In gimme_largest, a:\t\t %p\n", a);
printf("In gimme_largest, a + 5:\t %p\n", a + 5);
printf("In gimme_largest, lastPlusOne:\t %p\n", lastPlusOne);
while (a < lastPlusOne) {
if (*a > largest)
largest = *a;
a++;
}
return largest;
}
output:
In main, arr: 000000000062FE00
In main, arr + sizeof(arr): 000000000062FE14
In gimme_largest, a: 000000000062FE00
In gimme_largest, a + 5: 000000000062FE14
In gimme_largest, lastPlusOne: 000000000062FE14
The largest is 44

Iterating 2D array with pointer expressions in C

I'm practicing pointers and want to substitute pointer operations in place of the arrays to traverse through the elements of the array. I have read numerous articles and cannot grasp this concept. Can someone explain?
Here I made a 2D array and iterated through it using a basic nested for-loop, but want to use pointers;
int test[3][2] = {1,4,2,5,2,8};
for (int i = 0 ; i < 3; i++) {
for (int j = 0; j < 2; j++) {
printf("%d\n", test[i][j]);
}
}
int test[3][2] = {{1,4},{2,5},{2,8}};
// Define a pointer to walk the rows of the 2D array.
int (*p1)[2] = test;
// Define a pointer to walk the columns of each row of the 2D array.
int *p2 = NULL;
// There are three rows in the 2D array.
// p1 has been initialized to point to the first row of the 2D array.
// Make sure the iteration stops after the third row of the 2D array.
for (; p1 != test+3; ++p1) {
// Iterate over each column of the arrays.
// p2 is initialized to *p1, which points to the first column.
// Iteration must stop after two columns. Hence, the breaking
// condition of the loop is when p2 == *p1+2
for (p2 = *p1; p2 != *p1+2; ++p2 ) {
printf("%d\n", *p2);
}
}
In some compilers you can also use a single loop, treating a multidimensional array as a one-dimensional array read in row-major order.
This is mentioned in King's C Programming: A Modern Approach (2nd ed., p268).
#include <stdio.h>
int main(void)
{
int test[3][2] = {{1,4},{2,5},{2,8}}, *p;
for(p = &test[0][0]; p <= &test[2][1]; p++)
{
printf("%d\n", *p);
}
return 0;
}
Try the following and investigate
#include <stdio.h>
int main(void)
{
int test[3][2] = { { 1,4 }, { 2,5 }, { 2,8 } };
for ( int ( *p )[2] = test ; p != test + 3; ++p )
{
for ( int *q = *p; q != *p + 2; ++q ) printf( "%d ", *q );
puts( "" );
}
return 0;
}
The putput is
1 4
2 5
2 8
The first pointer is a pointer to an object of type int[2] that is it points to the first "row" of the array and then due to increments it points to other rows.. The second pointer is a pointer to an object of type int. It points to the first element of each row in the inner loop.
Treating a 2d array as 1d array is very easy using pointer arithmetic to iterate.
void print_2d_array(int *num, size) {
int counter = 0;
while (counter++ < size) {
printf("%i ", *num);
num++;
}
printf("\n");
}
int main() {
int matrix[2][3] = {{2, 11, 33},
{9, 8, 77}};
int matrix_size = sizeof(matrix) / sizeof(int); // 24 bytes / 4 (int size) = 6 itens
print_2d_array(matrix, matrix_size);
return 0;
}
If pointer declaration is the goal of your practice, use the following initialization:
int (*pTest)[rmax][cmax] = test;
Once you do that, the syntax of using pointer indexing mirrors that of array indexing, except that you have to use the * de-referencing operator.
for (int i= 0; i < 3; i++) {
for (int j= 0; j < 2; j++) {
printf ("%d ", *(pTest[i][j]));
}
printf ("\n");
}
However, if pointer arithmetic is the goal of your practice, then the following will work too:
int *res = &test;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
printf ("%d ", *(res + i*2 + j));
}
printf ("\n");
}
OUTPUT
1 4
2 5
2 8

Array of arrays, with different sizes

I'm having an array, that has arrays in every cell. For example, the big array is called arr:
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b}
Now the problem is, if I want to print the small arrs, inside the big array.
Here is my code:
#include <stdio.h>
void printArr(int arr [], int n)
{
for (int i = 0 ; i < n ; i++)
{
printf("%d ", *(arr + i));
}
printf("\n");
}
int main()
{
int a[5] = {1, 8, 4, 2, 0};
int b[3] = {1, 4, 2};
int *arr [2] = {a, b};
int n = 0;
for (int i = 0 ; i < 2 ; i++)
{
printArr(*(arr + i), n);
}
}
The output is supposed to be something like this:
1 8 4 2 0
1 4 2
But I can't get the size of each array, since sizeof(*(arr + i) gives me 4, which is the size of the pointer (the name of the array), and not all the array it self.
So what can I do?
Thanks!
The Problem:
The C language only provides a way of finding the size of types.
This gives the subtle differences between applying sizeof to:
1) An array of a type such as:
int a[3];
sizeof(a); // => 3 * sizeof(int)
2) A pointer to the type:
int *ptr;
sizeof(ptr); // => sizeof(int *)
or
int a[3] = {3, 2, 1};
int b[2] = {2, 1};
int *arr[2] = {a, b};
sizeof(arr[1]); // => sizeof(int *)
Some solutions:
Store the size
As jfly proposes store the size of the arrays.
Makes finding the size a constant time operation.
Append an end marker
Adding a end marker like '\0' as used for c-style strings.
You might use INT_MAX or INT_MIN in this case.
The printArr implementation would need to change to:
void printArr(int *arr)
{
int *it = arr;
while(arr != INT_MIN);
{
printf("%d ", *it);
}
printf("\n");
}
Disadvantages:
Finding the size of the array requires iterating over the full array.
Gives the risk of an actual value colliding with the end marker value.
Advantages:
The varying sized array can be passed as a single argument.
Using iterators
Store the pointer to the first and one past the last value.
void printArr(int *begin, int *end)
{
for (int *it = begin; it != end; it++)
{
printf("%d ", *it);
}
printf("\n");
}
int *end_arr[2] = {a + 3, b + 2};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], end_arr[i]);
}
Can be extended to other data structures.
Since arr is an array of pointers, so you can't get the size of array from the pointer which points to an array, you need additional size info:
int size_arr[2] = {sizeof(a) / sizeof(int), sizeof(b) / sizeof(int)};
for (int i = 0 ; i < 2 ; i++)
{
printArr(arr[i], size_arr[i]);
}

value of pointer to a char array vs plain char pointer

I am having a hard time understanding where I can use a pointer to an array,
e.g: char (*a)[10];.
So two basic questions.
Please give me a simple example of how just a pointer to an array can be used in C code.
Why would one use it as apposed to just declaring a variable as a pointer and then incrementing/decrementing the address after that point.
Say you have a database query that returns a set of strings. Further, say that you know that these strings are no longer than 9 characters in length. Only, you don't know how many elements are in the set returned by the query.
char (*a)[10] = malloc( NumRecords * sizeof *a );
if ( a == NULL )
{
/* Handle error appropriately */
return EXIT_FAILURE; /* Naive */
}
for ( i = 0 ; i < NumRecords ; ++i )
{
assert(strlen(DbRecordSet[i]) < 10);
strcpy(a[i], DbRecordSet[i]);
}
Example: how to print the elements of an array of num_row rows and 3 columns:
#include <stdio.h>
#define NUM_ROW(x) (sizeof (x) / sizeof *(x))
// print elements of an array of num_row rows and 3 columns
void print(int (*a)[3], size_t num_row)
{
size_t num_col = sizeof *a / sizeof **a;
for (int i = 0; i < num_row; i++) {
for (int j = 0; j < num_col; j++) {
printf("%d\n", a[i][j]);
}
}
}
int main(void)
{
int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
int b[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
print(a, NUM_ROW(a));
print(b, NUM_ROW(b));
return 0;
}
Any time you pass an expression with a multi-dimensioned array type to a function, you're going to be working with a pointer to an array:
int a[10][20];
foo(a);
void foo(int (*p)[20]) // or int p[][20]
{ ... }

Resources