Sum of an array - c

I can't understand why my program only prints the first number in the array.
it seems it loops only once and then something breaks the loop. The output is 232.
#include <stdio.h>
int main( int argc, char* argv[]){
int sum_arr(int arr[]);
int arr[5]={232,44,3,4,5};
printf("%d\n",sum_arr(arr));
return 0;
}
sum_arr(int arr[]){
int i,sum=0,sizeofarr=sizeof(arr)/sizeof(arr[0]);
for(i=0;i<=(sizeofarr-1);i++){
sum+=arr[i];
}
return (sum);
}

sizeofarr = sizeof(arr) / sizeof(arr[0]);
This trick to calculate the size of an array doesn't work. Because in the function, arr decays to a pointer, not an array.
To fix the problem, pass the size explicitly.

Change the code the following way
#include <stdio.h>
nt main( int argc, char* argv[])
{
int sum_arr( int arr[], size_t n );
int arr[5] = { 232, 44, 3, 4, 5 };
printf( "%d\n", sum_arr( arr, sizeof( arr ) / sizeof( *arr ) ) );
return 0;
}
int sum_arr( int arr[], size_t n )
{
int i = 0, sum = 0;
for ( ; i < n ;i++ )
{
sum += arr[i];
}
return ( sum );
}
The problem with your code is that an arrray passed as an argument is implicitly converted to a pointer to its first element. So inside function sum_array you used sizeof( int * ) / sizeof( int ) that for your system is equal to 1.
Take into account this quote 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.

Remember, in C when pass an array as an argument to a function, actually you're passing a pointer to an array.
Since the size of a pointer and an int is 4 or 8, you'll be getting sizeof(int *)/sizeof int (4/4=1 for 32-bit machines and 8/4=2 for 64-bit ones) which is 1 or 2.

In conclusion, array names in a C program are (in most cases) converted to pointers.One exception is when we use the sizeof operator on an array. If arr was converted to a pointer in this contest, sizeof(arr) would give the size of a pointer and not of the actual array, which would be rather useless, so in that case a means the array itself.
In my program the array passed in the function is converted to a pointer. Then, sizeof(arr) in the sum_arr function gives the size of a pointer and not of the actual array.
This program should be execute in this way:
#include <stdio.h>
#define SIZEOFARR(arr) (sizeof(arr)/sizeof(arr[0]))
int main(){
int sum_arr(int arr[],int size);
int arr[5]={232,44,3,4,5};
printf("The sum of the array is: %d\n",sum_arr(arr,SIZEOFARR(arr)));
return 0;
}
int sum_arr(int arr[],int size){
int i,sum=0;
for(i=0;i<size;i++){
sum+=arr[i];
}
return (sum);
}

Related

How do Array Pointers behave?

I was trying to write the code for storing multiplication table in array.
First I wrote the following code.
#include<stdio.h>
void Multiplication(int arr[][10], int num,int size);
int main(){
int arr[3][10];
Multiplication(&arr[0],2,3);
Multiplication(&arr[1],7,3);
Multiplication(&arr[2],9,3);
for(int i=0;i<3;i++){
printf("\n\nMultiplication Table of %d\n\n",arr[i][0]);
for(int j=0;j<10;j++){
printf("%d * %d = %d\n",arr[i][0],j,arr[i][j]);
}
}
return 0;
}
void Multiplication(int arr[][10], int num, int size){
for(int j=0;j<size;j++){
for(int i=0;i<10;i++){
arr[j][i] = num * (i+1);
}
}
}
When I was checking whether there is any reduntant part, I removed a little bit of pieces.
#include<stdio.h>
void Multiplication(int *arr, int num,int size);
int main(){
int arr[3][10];
Multiplication(arr[0],2,3);
Multiplication(arr[1],7,3);
Multiplication(arr[2],9,3);
for(int i=0;i<3;i++){
printf("\n\nMultiplication Table of %d\n\n",arr[i][0]);
for(int j=0;j<10;j++){
printf("%d * %d = %d\n",arr[i][0],j,arr[i][j]);
}
}
return 0;
}
void Multiplication(int *arr, int num,int size){
for(int i=0;i<10;i++){
arr[i] = num * (i+1);
}
}
Now, I noticed that &arr[0] and arr[0] are behaving same? I wanna know why is it so?
The following is the question asked:
I noticed that &arr[0] and arr[0] are behaving same? I wanna know why is it so?
We have
int arr[3][10];
arr[0] is a int[10], which is to say an array of 10 int values.
But it's being treated as a pointer. When an array is treated as a pointer, it produces a pointer to the first element of the array. So this means arr[0] is automatically converted to a int* pointing to the first element of the first row of arr when necessary.
&arr[0] means &(arr[0]). It produces a int(*)[10] (a pointer to an array of 10 int values) pointing to the first row of arr.
To recap,
arr[0] is a int[10] which degrades to a int*.
It points to the first element of the first row of arr.
&arr[0] is a int(*)[10].
It points to the first row of arr.
So, arr[0] is NOT equivalent to &arr[0], contrary to your assertion.
And this lack of equivalence is why you had to change from &arr[0] when you when you had int arr[][10] (which means int (*arr)[10] a parameter), to arr[10] when you had int *arr as the parameter.
The both programs are incorrect.
You declared a two dimensional array
int arr[3][10];
So expressions like this arr[0], arr[1], arr[2] have the array type int[10]. That is they produce the first "row", the second "row" and the third "row" of the two-dimensional array.
In the first program you are calling the function Multiplication like
Multiplication(&arr[0],2,3);
Multiplication(&arr[1],7,3);
Multiplication(&arr[2],9,3);
and within the function there are two nested loops
void Multiplication(int arr[][10], int num, int size){
for(int j=0;j<size;j++){
for(int i=0;i<10;i++){
arr[j][i] = num * (i+1);
}
}
}
according to the argument specified for the parameter size the function deals with a two dimensional array with three elements (rows) of the array type int[10] using a pointer to the first element of the array. As a result for the argument expressions &arr[1] and &arr[2] there is an access to the memory beyond the original two dimensional array.
You may consider these calls
Multiplication(&arr[0],2,3);
Multiplication(&arr[1],7,3);
Multiplication(&arr[2],9,3);
like
Multiplication( arr, 2, 3 );
Multiplication( arr + 1, 7, 3 );
Multiplication( arr + 2, 9, 3 );
The array designator arr is implicitly converted to a pointer to its first element (row) of the type int ( * )[10].
As you are setting only one "row" within the array then the function can be declared and defined the following way
void Multiplication(int arr[][10], int num ){
for(int j=0;j < 10;j++){
( *arr )[j]= num * (j+1);
}
}
and called like
Multiplication( arr, 2 );
Multiplication( arr + 1, 7 );
Multiplication( arr +2, 9 );
Of you want to set elements of a sub-array then the function can be defined the way it is defined initially but called like
Multiplication( arr, 2, 3 );
Multiplication( arr + 1, 7, 2 );
Multiplication( arr +2, 9, 1 );
In the second program the function is declared like
void Multiplication(int *arr, int num,int size){
for(int i=0;i<10;i++){
arr[i] = num * (i+1);
}
}
and you are calling it like
Multiplication(arr[0],2,3);
Multiplication(arr[1],7,3);
Multiplication(arr[2],9,3);
But within the function the parameter size is not used. There is used the magic number 10. And the passed argument 3 does not make a sense.
You should declare the function like
void Multiplication(int *arr, int num,int size){
for(int i=0;i<size;i++){
arr[i] = num * (i+1);
}
}
and call it like
Multiplication(arr[0],2,10);
Multiplication(arr[1],7,10);
Multiplication(arr[2],9,10);

Header function average gives me wrong result in C. If I call the "average" function which I have created in my header, the result is not as expected

I have created an header file in C and called it statistic.h. I have created a function to calculate the average ( I called the function "average"). But when I use to formula :
sizeof (list)/sizeof (list[0]) , the result is wrong.
header file below:
#ifndef STATISTIC_H_INCLUDED
#define STATISTIC_H_INCLUDED
float average(int list[]){
int i;
float sum_elements,mean;
int total =sizeof (list)/sizeof (list[0]);
for (i=0;i<total;i++){
sum_elements=sum_elements+list[i];
}
mean = sum_elements / total;
return mean;
}
#endif // STATISTIC_H_INCLUDED
//see main code below where I'm trying to call the function I have previously created in the header.
#include <stdio.h>
#include "statistic.h"
int main(){
int list[]={26,12,16,56,112,24};
float mean=average(list); // I'm calling the average function I created in my header
printf("%f",mean);
return 0;
/*The average is 41.00 but I'm getting 19.00 instead . If I don't use
the sizeof function and manually declare the variable total=6 (the
number of element in the list), it gives me the correct result
(41.00).*/
sizeof (list)/sizeof (list[0]); in average doesn't work since list decays into an int* when passed as an argument to the function. You need to send the size of the list into the function as an argument.
Example:
#include <stddef.h>
#include <stdio.h>
float average(int list[], size_t total) { // send total in as an argument
float sum_elements = 0; // note: initialize sum_elements
for (size_t i = 0; i < total; i++) {
sum_elements = sum_elements + list[i];
}
return sum_elements / total;
}
int main() {
int list[] = {26, 12, 16, 56, 112, 24};
// do the size calculation here, where `list` is defined instead:
float mean = average(list, sizeof list / sizeof *list);
printf("%f", mean);
return 0;
}
Demo
The list parameter in your average function isn't an array, it's a pointer, so the sizeof trick doesn't work.
Unless it's the operand of the sizeof or unary & operators, or a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted, or "decay", to an expression of type "pointer to T" and its value will be the address of the first element in the array.
When you call average:
float mean=average(list);
the expression list is converted from type "6-element array of int" to "pointer to int" and the value of the expression is the same as &list[0], so what average actually receives is a pointer value, not an array.
In the context of a function parameter declaration, T a[N] and T a[] are both "adjusted" to T *a - all three declare a as a pointer to T, not an array of T.
You will have to pass the array size as a separate parameter:
float average( int *list, size_t list_size )
{
...
for ( size_t i = 0; i < list_size; i++ )
...
}
and call it as
mean = average( list, sizeof list / sizeof list[0] );
You also need to explicitly initialize sum_elements to 0 in the average function.

Regarding question about function pointer in C?

I was reading about function pointer. That it contains address of instructions. And there I encountered one question to find an element in array using function pointer. Here is the code.
#include <stdio.h>
#include <stdbool.h>
bool compare(const void* a, const void* b)
{
return (*(int*)a == *(int*)b);
}
int search(void* arr, int arr_size, int ele_size, void* x, bool compare(const void*, const void*))
{
char* ptr = (char*)arr; // Here why not int *ptr = (int*)arr;
int i;
for (i = 0; i < arr_size; i++)
{
if (compare(ptr + i * ele_size, x))
{
return i;
}
}
return -1;
}
int main()
{
int arr[] = { 2, 5, 7, 90, 70 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = 7;
printf("Returned index is %d ", search(arr, n, sizeof(int), &x, compare));
return 0;
}
In the search function char *ptr = (char*)arr; is used which is giving perfect answer = 2.
But when I have used int *ptr = (int*)arr; it gives -1 as answer.
Why is this? Can anyone explain this?
A char is the smallest addressable unit in any C program, and on most system it corresponds to a single byte. That treats the array as a generic sequence of bytes, and uses the ele_size to calculate the byte-position of each element with ptr + i*ele_size.
If you use int *ptr then the byte-position calculation will be wrong by a factor of sizeof(int) (typically 4), since the pointer arithmetic will be done in units of the base type (int instead of char).
The function search knows nothing about what is the type of elements of the array pointed to by the pointer arr of the type void *.
So casting the pointer to the type int * does not make a sense. If to do so then the expression ptr + i*ele_size where the pointer arithmetic is used will produce an incorrect result.
That it contains address of instructions
There is a subtle difference between normal (object) pointers and function pointers. It is not possible to access the single instructions of a function - they do not have the same length.
With other pointers the increment (arithmetic) is adapted to the type, whether as p[i] or p + i or *(p+i).
Side note: there still is int at the bottom of the call chain:
return (*(int*)a == *(int*)b);

Get count of an array from within a function

I'm trying to write a function that prints the elements of a given array. However, I don't understand how I can count the elements of the array which is passed into my function. Here's the code:
In this example, I am trying to get the count from within my function, though this only returns 1.
#include <stdio.h>
void first_function(int ages[], char *names[]) {
int i = 0;
int count = sizeof(*ages) / sizeof(int);
for(i = 0; i < count; i++) {
printf("%s has lived %d years.\n", names[i], ages[i]);
}
}
int main(int argc, char *argv[])
{
int ages[] = { 7, 32, 36 };
char *names[] = {
"Tiger", "Sandy",
"Ryan"
};
first_function(ages, names);
printf("---\n");
return 0;
}
In this example, I give the function an extra parameter (count), then get the count from within main. Is this the normal way to do it? It seems unclean somehow.
#include <stdio.h>
void first_function(int ages[], char *names[], int count) {
int i = 0;
for(i = 0; i < count; i++) {
printf("%s has lived %d years.\n", names[i], ages[i]);
}
}
int main(int argc, char *argv[])
{
int ages[] = { 7, 32, 36 };
char *names[] = {
"Tiger", "Sandy",
"Ryan"
};
int count = sizeof(ages) / sizeof(int);
first_function(ages, names, count);
printf("---\n");
return 0;
}
Your so-called unclean way is the normal way. (The sizeof idiom does not work if the array parameter has decayed to a pointer type). Although consider using a size_t type for the count, not an int.
Another approach is to use a particular value to signal the end of the array. Effectively this is how the string library functions work in C; with NUL signalling the end of the string.
According to the C Standard (6.7.6.3 Function declarators (including prototypes))
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted
to ‘‘qualified pointer to type’’, where the type qualifiers (if any)
are those specified within the [ and ] of the array type
derivation....
So this function declaration
void first_function(int ages[], char *names[]);
is equivalent to the following declaration after adjusting the corresponding parameters declared like arrays.
void first_function( int *ages, char **names );
That is the parameters ages and names have pointer types within the function.
As result this expression
int count = sizeof(*ages) / sizeof(int);
(I think you mean
int count = sizeof(ages) / sizeof(int);
^^^^
nevertheless)
is equivalent to
int count = sizeof( int) / sizeof(int);
because the type of the sub-expression *ages is int.
If you will write the expression like
int count = sizeof(ages) / sizeof(int);
then it is equivalent to
int count = sizeof(int *) / sizeof(int);
and again will not yield the size of the array passed as the argument.
For such arrays that do not have a sentinel value you have to pass also their sizes to functions if it is required.
Thus the function should be declared like
void first_function(int ages[], char *names[], size_t n);
and called like
size_t count = sizeof(ages) / sizeof(*ages);
first_function(ages, names, count);
Pay attention to that there is no need to initialize the variable i within the function two times. The function can look like
void first_function(int ages[], char *names[], size_t count)
{
for ( size_t i = 0; i < count; i++)
{
printf("%s has lived %d years.\n", names[i], ages[i]);
}
}
Yes you can't use sizeof here to get the length of the array in the called function. Because array decays into pointer here in the called function. And that's why it will return sizeof pointer not size of array.
Solution- you need to pass another parameter specifying the size of the array or keeping a place holder like NULL or some value to mark the end of the array. (Well you have followed that in your second solution - which is perfectly fine and it works).
Return value of sizeof is size_t. Use size_t instead of int.
It's the right way to handle what sizeof operator returns.

1-d pointer to a 2-d array

#include<stdio.h>
void display(int (*p)[3],int,int);
int main()
{
int a[3][4] = {1,2,3,4,
5,6,7,8,
9,0,1,6};
display(a,3,4);
}
void display(int (*p)[3],int r,int c)
{
int i,j,*q;
for(i=0;i<r;i++)
{
q=p+i;
for(j=0;j<c;j++)
printf("%d",*(q+j));
printf("\n");
}
}
this does not work but if we write
void dis(int (*p)[4],int,int);
it works
that is if we have a pointer of array having number of columns as number of element in array
Arrays used in expressions with rare exceptions are converted to pointers to their first element.
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.
So if you have an array declared like
T a[N];
where T is some type and N is some integral expression then the array can be converted to a pointer the following way.
First of all let's rewrite the declaration the following way
T ( a[N] );
Now to get pointer just substitute the declarator in the parentheses a[N] for *p. For example
T ( a[N] );
T ( *p ) = a;
So if you have a multidimensional array like this
T a[N1][N2];
then pointer to its first element can be defined the following way
T ( a[N1] )[N2];
T ( *p )[N2] = a;
In general case you can use the rule
T a[N1][N2]...[Nn];
is equivalent to
T ( a[N1] )[N2]...[Nn];
and a pointer is defined like
T ( a[N1] )[N2]...[Nn];
T ( * p )[N2]...[Nn] = a;
In your program you have the declaration
int a[3][4] = {1,2,3,4,
5,6,7,8,
9,0,1,6};
that can be rewritten as it has been shown above like
int ( a[3] )[4] = {1,2,3,4,
5,6,7,8,
9,0,1,6};
So the pointer to the first element of the array will have the type int ( * )[4]
Thus the function shall be declared at least like
void display( int (*)[4], int, int);
Take into account that within the function
void display(int (*p)[4],int r,int c)
{
int i,j,*q;
for(i=0;i<r;i++)
{
q=p+i;
for(j=0;j<c;j++)
printf("%d",*(q+j));
printf("\n");
}
}
there is an assignment of incompatible types
q=p+i;
The expression p + i has the type int ( * )[4] while the pointer q has the type int *.
It shall be written
q = *( p + i );
In this case the expression *( p + i ) has the type int[4] that is implicitly converted to pointer of the type int *
Also according to the C Standard the function main without parameters shall be declared like
int main( void )
If to use only pointers instead of indices to access elements of the array then the function can look the following way as it is shown in the demonstrative program
#include <stdio.h>
#define COLS 4
void display( int (*)[COLS], size_t );
int main( void )
{
int a[][COLS] =
{
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 0, 1, 6 }
};
const size_t ROWS = sizeof( a ) / sizeof( *a );
display( a, ROWS);
}
void display( int (*p)[COLS], size_t rows )
{
for ( int ( *p_row )[COLS] = p; p_row != p + rows; ++p_row )
{
for ( int *p_col = *p_row; p_col != *p_row + COLS; ++p_col )
{
printf( "%d ", *p_col );
}
putchar( '\n' );
}
}
Its output is
1 2 3 4
5 6 7 8
9 0 1 6
Arrays naturally decays to pointers to their first element. That is, a will decay to a pointer to a[0], i.e. &a[0].
And what is a[0]? It's an array of four int elements. So &a[0] is a pointer to an array of four int elements, or int (*)[4].
You should write void display(int (*p)[4],int,int) exactly like that.
because when you write int a[3][4] c see this like three pointers to 3 arrays of 4 elements each.

Resources