Program does not find highest number in array as intended - arrays

This program is supposed to return the highest number in the array "array". But it only returns the highest number between the first and second numbers. Why?
#include <stdio.h>
#include <stdlib.h>
int HighestNumber(int* array)
{
int highest = INT_MIN;
for(size_t x = 0; x < sizeof(array) / sizeof(array[0]); x++)
if(array[x] > highest)
highest = array[x];
return highest;
}
int main()
{
int *array = (int*)malloc(4*sizeof(int));
array[0] = 66;
array[1] = 552;
array[2] = -17;
array[3] = 1000;
printf("%d", HighestNumber(array));
return 0;
}

The function parameter array has the pointer type int *.
int HighestNumber(int* array);
So the expression sizeof(array) / sizeof(array[0]) is equivalent to expression sizeof( int * ) / sizeof( int ) and yields usually either value 2 or 1 dependent of the sizes of pointers and integers.
You need explicitly to pass the number of elements in the array As for example
int HighestNumber(int* array, size_t n );
Pay attention to that the user can pass 0 for the parameter n. In this case using your approach to the function definition the function can return an invalid value.
The function should be declared and defined the following way. As the function does not change the processed array then the first parameter should have the qualifier const.
size_t HighestNumber( const int *array, size_t n )
{
size_t highest = 0;
for ( size_t i = 1; i < n; i++ )
{
if ( array[highest] < array[i] )
{
highest = i;
}
}
return highest;
}
And the function is called like
printf("%d\n", array[HighestNumber(array, 4 )] );
or
size_t highest = HighestNumber(array, 4 );
printf( "The largest number is %d at the position %zu\n",
array[highest], highest);
As you can see the advantage of such function definition is that you can also determine the position where the highest element is stored in the array.
Pay attention to that you need to free the dynamically allocated memory.
free( array );

The sizeof trick doesn't work on pointers!
If applied to pointers you get the (truncated) ratio between the size of a pointer, which is always the same, no matter how large your array is, and the size of a single element in that array, so in your case with int* most likely either 2 (64-bit system, typically 8-byte pointers, 4-byte int) or 1 (32-bit system, typically 4-byte pointers, 4-byte int), though other systems can yield yet other values, but still not the required one (apart from accidentally matching array size...).
To use sizes on array you need to pass it explicitly by another parameter:
int highestNumber(size_t length, int* array)
{
int highest = INT_MIN;
while(length--)
{
if(*array > highest)
{
highest = *array;
}
++array;
}
return highest;
}
while you can then apply the sizeof trick on the array being passed to:
int array[4];
// assign values to
// array has not yet decayed to pointer, thus you can do:
int highest = highestNumber(sizeof(array)/sizeof(*array), array);
However in your example you use a dynamically allocated array – these only can be stored in pointers, thus there's no way around tracking the size explicitly:
size_t length = 4;
int* array = malloc(length * sizeof(*array));
// assign values
int highest = highestNumber(length, array);
Final note: You might as well use the length/size as second parameter, of course; having it as first would allow for:
int highestNumber(size_t length, int array[length]);
which is fully equivalent, as for the outermost dimension an explicitly specified array size is ignored and the parameter still remains a pointer (note that this does not apply for further dimensions), but this declaration expresses more explicitly what the function actually expects as arguments.
Edit (stealing from Vlad from Moscow's answer):
As you do not (intend to) modify the array within the function it is a good choice to accept a pointer to const – this allows to use both non-const and const arrays while the original function signature excludes the latter without need:
int highestNumber(size_t length, int const* array)
int highestNumber(size_t length, int const array[length]);

The moment you pass array to the function HighestNumber(), you lose the size information of the array. This is called an array-to-pointer decay.
To the function HighestNumber() it only sees a pointer, without knowing anything about the array.
Consider pass the array size as the second parameter to the function, such as
int HighestNumber(int* array, size_t num) {
// ..
}

An array decays to a pointer in function parameters. sizeof on a pointer then returns the size of the pointer, and not the pointed to data.
Possible solution:
Pass the size of the array as the second argument.
int HighestNumber(int* array, size_t size) {
//...
}

Related

Write a signature of function accepts all 2D arrays of type int as parameter regardless of the method the user chose?

An example to illustrate:
#include <stdlib.h>
#include<stdio.h>
void simple_function(int s , int array[][s]);
int main(void){
int x;
/*Static 2D Array*/
int array[2][2];
/*Many Methods to Dynamically Allocate 2D Array....for example*/
/* Using Array of pointers*/
int *array1[2];
for(x=0;x<2;x++){array1[x] = calloc (2, sizeof(int));}
/*Using pointer to a pointer */
int **array2 = calloc (2, sizeof(int*));
for(x=0;x<2;x++){array2[x] = calloc (2, sizeof(int));}
/*Using a single pointer*/
int *array3 = calloc (4 , sizeof(int));
/* Codes To Fill The Arrays*/
/*Passing the Arrays to the function, some of them won't work*/
simple_function(2, array); /*Case 1*/
simple_function(2, array1); /*Case 2*/
simple_function(2, array2); /*Case 3*/
simple_function(2, array3); /*Case 4*/
return 0;
}
void simple_function (int s, int array[][s]){
int x,y;
for(x=0;x<s;x++){
for(y=0;y<s; y++){
printf ("Content is %d\n", array[x][y]);
}
}
}
My Question:
Is there a way to write the signature of the simple_function to let it accepts all cases regardless of the method that the user chose? If not, what is the most preferable for the function if I want to make a library?
You've actually declared two different types of objects, as shown below
Your array and array3 are both stored in memory as 4 contiguous ints. There's no additional information, you've simply reserved space for 4 ints, and the C specification requires that they are contiguous.
However, array1 and array2 are actually pointer arrays. Your code reserves memory for an array of two pointers, and each pointer points to an array of two ints. The ints will be arranged in groups of two, but the groups can be scattered anywhere in memory.
From this, it should be clear that the compiler cannot use the same code to access both types of array. For example, let's say that you're trying to access the item at array[x][y]. With a contiguous array, the compiler computes the address of that item like this
address = array + (x * s + y) * sizeof(int)
With a scattered array, the compiler computes the address like this
pointer = the value at {array + x * sizeof(int *)}
address = pointer + y * sizeof(int)
So you need two functions to handle those two cases. For the contiguous array, the function looks like this
void showContiguousArray( int s, int array[][s] )
{
for ( int x=0; x<s; x++ )
for ( int y=0; y<s; y++ )
printf( "array[%d][%d] = %d\n", x, y, array[x][y] );
}
For the scattered array, the function is
void showScatteredArray( int s, int **array )
{
for ( int x=0; x<s; x++ )
for ( int y=0; y<s; y++ )
printf( "array[%d][%d] = %d\n", x, y, array[x][y] );
}
Notice that those functions are identical, except for one thing, the type of the array argument. The compiler needs to know the type in order to generate the correct code.
If the array is declared in the same scope where it's used, then all of these details are hidden, and it seems that you're using the exact same code to access different types of arrays. But that only works because the compiler knows the type of the array from the earlier declaration. But if you want to pass the array to a function, then the type information must be explicitly specified in the function declaration.
Is there a way to write the signature of the simple_function to let it accepts all cases regardless of the method that the user chose?
"All the cases" apparently describes the different declarations array, array1, array2, and array3, the latter three of which are described in code comments as "Methods to Dynamically Allocate 2D Array." But none of the four types are the same as any of the others, and none of the latter three in fact declare 2D arrays nor pointers to such. None of them are even compatible with each other. Of the dynamic ones, only array3 can even usefully be converted to something comparable to array.
A dynamically-allocated 2D array would be referenced via a pointer of this type:
int (*array4)[2];
array4 = calloc(2 * sizeof(*array4));
So, no.
If not, what is the most preferable for the function if I want to make a library?
It depends on your objectives. If your function must be compatible with static 2D arrays, then something of the general form you presented, plus or minus the variable dimension, is the only alternative. If you want to support the pointer-to-pointer form, then that's fine, and usable with declarations like array1's and array2's, but not with array, array3, or array4.
Assuming that you want this for 2D arrays, perhaps this can get you started ...
void simple_function(int s, int t , int* array) {
int i, j;
for (i=0; i<s; i++) {
for (j=0; j<t; j++) {
// accessing your array elements
printf(" %d", *(array + i*t + j));
}
printf("\n");
}
}
int main(void)
{
int array[2][3];
array[0][0] = 1;
array[0][1] = 2;
array[0][2] = 3;
array[1][0] = 11;
array[1][1] = 12;
array[1][2] = 13;
array[2][0] = 21;
array[2][1] = 22;
array[2][2] = 23;
simple_function(3, 3 , array);
return 0;
}
The expression int **array2 is not a 2D array by the way, it is a variable that holds the address of a pointer variable.

Acessing a 2D array inside a function

I have a function which accepts int* pInput[] as an argument.
void Process(int* pInput[], unsigned int num);
I have to call this function via 2 methods as
main()
{
int *pIn[2];
int input[2][100] = {0};
pIn[0] = ( int* )malloc( 100 * sizeof( int) );
pIn[1] = ( int* )malloc( 100 * sizeof( int) );
Process( pIn, 2 );
Process( ( int** )input, 2 );
}
Then how can i access each value of pInput inside function 'Process'?I cannot access it directly as pIn[0][0].
how can i access each value of pInput inside function 'Process'?I cannot access it directly as pIn[0][0].
No! You can access it exactly that way: pInput[0][0] if the input you pass is pIn. This is because pIn is an array of int*s I.e. it's of type int *[n] each of its element pointing to an array of ints. It would decay into int**.
However, if you want to pass input, a 2D array of ints, you've to do more since a 2D array doesn't decay into a double pointer, T** but into a pointer to an array, T (*) [n]. This is because array decay is not recursive, it happens only to the first level. Alternatively, you can do this (Live example)
pIn[0] = input[0];
pIn[1] = input[1];
and now pass pIn to Process. Here pIn is a surrogate for input and it needs to have as many elements as input, which is not a very elegant solution. A better way to pass input, when you know the dimensions during compile-time is
void Process(int (*pInput)[100], size_t rows) { }
void Process(int input [2][100], size_t rows) { }
/* These two are the same; the compiler never sees the `2`. input's type is int(*)[100] */
Read on array decay to understand the situation better.
Aside
Do I cast the result of malloc? No, you do not need to cast the return value of malloc in C.
What should main() return in C and C++? The return type of main should be int.
Related
C-FAQ: My compiler complained when I passed a two-dimensional array to a function expecting a pointer to a pointer.
What is array decaying?
Why can we omit the first dimension of a multidimensional array when we are passing it to a function
In your process() function you just need to access it normally like any 2d array as below. Calling both ways are same.
void Process( int * pInput[], unsigned int num)
{
printf(" %d", pInput[0][0]); //printing value of pInput[0]
printf(" %d", pInput[1][0]); //printing value of pInput[1]
pInput[0][0] = 8054; // changing its value.
pInput[1][0] = 8055; // changing its value.
}
int main()
{
int *pIn[2];
int input[2][100] = {0};
pIn[0] = ( int* )malloc( 100 * sizeof( int) );
pIn[1] = ( int* )malloc( 100 * sizeof( int) );
// assigning value to array.
pIn[0][0] = 23;
pIn[0][1] = 2;
pIn[1][0] = 5689;
pIn[1][1] = 5643;
Process( pIn, 2 ); //calling process funtion
printf(" %d", pIn[1][0]); //printing the changed value by process funtion.
}
You are getting confused because you are using different types when there's no need for such. Arrays follow the same rules of indirection as any other type. If you would allocate a plain int dynamically, you would write int* x = malloc(sizeof(*x));. Simply do the very same thing when it comes to arrays. Don't confuse things by mixing in the "arrays decay to pointers" rule.
So we have int input[2][100], very straight-forward, it is a plain 2D array. Now if you want to allocate that dynamically, you will need a pointer to such an array:
int (*pIn)[2][100]; // pointer to an array of int [2][100].
pIn = malloc(sizeof(*pIn));
And the whole program would then be:
#include <stdlib.h>
void Process (size_t num, int pInput[num][100])
{
}
int main (void)
{
int (*pIn)[2][100];
int input[2][100] = {0};
pIn = malloc(sizeof(*pIn));
if(pIn == NULL)
{
// error handling
return 0;
}
Process(2, *pIn);
Process(2, input);
free(pIn);
return 0;
}
Comments:
size_t is the most correct type to use for array sizes, as it is the type returned by the sizeof operator. So it is just an unsigned integer with a fancy name.
int pInput[num][100] in the function will actually decay into an array pointer to an array of 100 int. You don't need to know that to use it though, simply use pInput[x][y] and pretend it is a 2D array. The important thing here is to understand that the array is not passed by value.
The correct form of main is int main (void).
Casting the result of malloc is pointless.
Always check the result of malloc and remember to clean up allocated data.

c sizeof function of an array in a function is always four bytes despite the number of array elements [duplicate]

This question already has answers here:
"sizeof" to know the size of an array doesn't work in a function in C [duplicate]
(2 answers)
Closed 6 years ago.
When I print the (size of the array/size of the the first element), I get the right answer, but when I do the same thing in the function, I get the size of the array to be four and the size of the first element of the array to be four hence the division is always one.
#include<stdio.h>
int sizer(int *);
int main()
{
int num;
printf("Please an index: ");
scanf("%d",&num);
int array[num];
int size = sizer(array); //function to calculate array length
/*answer is always 4*/
printf("%d\n", size);
/*answer is correct*/
printf("%d\n", sizeof(array) / sizeof(array[0]));
return 0;
}
/*function to calculate array length*/
int sizer(int *array)
{
return sizeof(array) / sizeof(array[0]);
}
sizeof is not a function called at runtime, even though it looks like one. It is a feature of the compiler. It looks at a data object and replaces the sizeof() expression with a constant.
int arr[10];
int size = sizeof(arr)/sizeof(int);
This works because the compielr can see how big arr is. arr is a statically sized array here. Both sizeof expressions are replaced with the appropriate values.
int arr[10];
int size = sizer(arr);
....
int sizer(int array[]) {
return (sizeof(array)/sizeof(int));
}
This doesn't work. In sizer, array looks like an array but arrays passed in as parameters are actually just pointers to the array type. So sizeof(array) is equivalent to sizeof(int *)
scanf("%d",&num);
int arr[num];
int size1 = sizeof(arr)/sizeof(int);
int size2 = sizer(arr);
....
int sizer(int array[]) {
return (sizeof(array)/sizeof(int));
}
Here, size1 works but size2 doesn't. The creation of arr is actually allocated like this:
int arr_sizeof = sizeof(int)*num;
int *arr = alloca(arr_sizeof);
Then later on, sizeof(arr) is quietly replaced with arr_sizeof. But the compiler can only do this in the same scope that arr is created, because when arr is passed to sizer it's just converted to an int * again, so the size information is not carried over. sizer fails for thet same reason, arrays in function parameters are just passed along as simple pointers.
When you pass an array to a function you are really just passing a pointer to the first element, so in the body of sizer, the parameter array is just a pointer to int. Your function correctly returns sizeof(int*)/sizeof(int) (which is 2 rather than 4 on my machine), though this is probably not what you want. There really isn't any way for a function in C to compute the length of a passed array, which is why it is standard in C to pass the number of elements in an array as one of the parameters in any function which takes an array parameter.

Returning a two-dimensional array in C?

I recently started programming C just for fun. I'm a very skilled programmer in C# .NET and Java within the desktop realm, but this is turning out to be a bit too much of a challenge for me.
I am trying to do something as "simple" as returning a two-dimensional array from a function. I've tried researching on the web for this, but it was hard for me to find something that worked.
Here's what I have so far. It doesn't quite return the array, it just populates one. But even that won't compile (I am sure the reasons must be obvious to you, if you're a skilled C programmer).
void new_array (int x[n][n]) {
int i,o;
for (i=0; i<n; i++) {
for (o=0; o<n; o++) {
x[i][o]=(rand() % n)-n/2;
}
}
return x;
}
And usage:
int x[n][n];
new_array(x);
What am I doing wrong? It should be mentioned that n is a constant that has the value 3.
Edit: Here's a compiler error when trying to define the constant: http://i.imgur.com/sa4JkXs.png
C does not treat arrays like most languages; you'll need to understand the following concepts if you want to work with arrays in C.
Except when it is the operand of the sizeof or unary & operator, 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 converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. This result is not an lvalue; it cannot be the target of an assignment, nor can it be an operand to the ++ or -- operators.
This is why you can't define a function to return an array type; the array expression will be converted to a pointer type as part of the return statement, and besides, there's no way to assign the result to another array expression anyway.
Believe it or not, there's a solid technical reason for this; when he was initially developing C, Dennis Ritchie borrowed a lot of concepts from the B programming language. B was a "typeless" language; everything was stored as an unsigned word, or "cell". Memory was seen as a linear array of "cells". When you declared an array as
auto arr[N];
B would set aside N "cells" for the array contents, along with an additional cell bound to arr to store the offset to the first element (basically a pointer, but without any type semantics). Array accesses were defined as *(arr+i); you offset i cells from the address stored in a and dereferenced the result. This worked great for C, until Ritchie started adding struct types to the language. He wanted the contents of the struct to not only describe the data in abstract terms, but to physically represent the bits. The example he used was something like
struct {
int node;
char name[14];
};
He wanted to set aside 2 bytes for the node, immediately followed by 14 bytes for the name element. And he wanted an array of such structures to be laid out such that you had 2 bytes followed by 14 bytes followed by 2 bytes followed by 14 bytes, etc. He couldn't figure out a good way to deal with the array pointer, so he got rid of it entirely. Rather than setting aside storage for the pointer, C simply calculates it from the array expression itself. This is why you can't assign anything to an array expression; there's nothing to assign the value to.
So, how do you return a 2D array from a function?
You don't. You can return a pointer to a 2D array, such as:
T (*func1(int rows))[N]
{
T (*ap)[N] = malloc( sizeof *ap * rows );
return ap;
}
The downside to this approach is that N must be known at compile time.
If you're using a C99 compiler or a C2011 compiler that supports variable-length arrays, you could do something like the following:
void func2( size_t rows, size_t cols, int (**app)[cols] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...; // the parens are necessary
...
}
If you don't have variable-length arrays available, then at least the column dimension must be a compile-time constant:
#define COLS ...
...
void func3( size_t rows, int (**app)[COLS] )
{
*app = malloc( sizeof **app * rows );
(*app)[i][j] = ...;
}
You can allocate memory piecemeal into something that acts like a 2D array, but the rows won't necessarily be contiguous:
int **func4( size_t rows, size_t cols )
{
int **p = malloc( sizeof *p * rows );
if ( p )
{
for ( size_t i = 0; i < rows; i++ )
{
p[i] = malloc( sizeof *p[i] * cols );
}
}
return p;
}
p is not an array; it points to a series of pointers to int. For all practical purposes, you can use this as though it were a 2D array:
int **arr = foo( rows, cols );
...
arr[i][j] = ...;
printf( "value = %d\n", arr[k][l] );
Note that C doesn't have any garbage collection; you're responsible for cleaning up your own messes. In the first three cases, it's simple:
int (*arr1)[N] = func(rows);
// use arr[i][j];
...
free( arr1 );
int (*arr2)[cols];
func2( rows, cols, &arr2 );
...
free( arr2 );
int (*arr3)[N];
func3( rows, &arr3 );
...
free( arr3 );
In the last case, since you did a two-step allocation, you need to do a two-step deallocation:
int **arr4 = func4( rows, cols );
...
for (i = 0; i < rows; i++ )
free( arr4[i] )
free( arr4)
Your function return void, so the return x; line is superfluous. Aside from that, your code looks fine. That is, assuming you have #define n 3 someplace and not something like const int n = 3;.
You can't return an array in C, multidimensional or otherwise.
The main reason for this is that the language says you can't. Another reason would be that generally local arrays are allocated on the stack, and consequently deallocated when the function returns, so it wouldn't make sense to return them.
Passing a pointer to the array in and modifying it is generally the way to go.
To return (a pointer to) a newly-created array of dimensions known at compile time, you can do this:
#define n 10 // Or other size.
int (*new_array(void))[n]
{
int (*x)[n] = malloc(n * sizeof *x);
if (!result)
HandleErrorHere;
for (int i = 0; i < n; ++i)
for (int o = 0; i < n; ++o)
x[i][o] = InitialValues;
return x;
}
…
// In the calling function:
int (*x)[n] = new_array();
…
// When done with the array:
free(x);
If the size is not known at compile time, you cannot even return a pointer to an array. C does support variable-length arrays but not in the return types of functions. You could instead return a pointer to a variable-length array through a parameter. That requires using a parameter that is a pointer to a pointer to an array of variable length, so it gets somewhat messy.
Also, the preferred choices between allocating an array in the caller dynamically, allocating an array in the caller automatically, allocating an array in the called function dynamically and using variable-lengths arrays or fixed-length arrays or even one-dimensional arrays with manual indexing depend on context, including what how large the array might be, how long it will live, and what operations you intend to use it for. So you would need to provide additional guidance before a specific recommendation could be made.
In C there's only pass/return by value (no pass by reference). Thus the only way of passing the array (by value) is to pass its address to the function, so that it can manipulate it through a pointer.
However, returning by value an array's address isn't possible, since by the time control reaches the caller, the function goes out of scope and its automatic variables go down with it too. Hence if you really have to, you can dynamically allocate the array, populate and return it, but the preferred method is passing the array and leaving the onus of maintaining the array to the caller.
As for the error, the only warning I get in GCC for this is warning: 'return' with a value, in function returning void which is simply meaning that you shouldn't return anything from a void function.
void new_array (int x[n][n]); what you're really doing here is taking a pointer to an array of n integers; the decayed type is int (*x)[n]. This happens because arrays decay into pointers generally. If you know n at compile time, perhaps the best way to pass is:
#define n 3
void new_array (int (*x)[n][n]) {
int i,o;
for (i=0; i<n; i++) {
for (o=0; o<n; o++) {
x[i][o]=(rand() % n)-n/2;
}
}
}
And call it as
int arr[n][n];
new_array(&arr);
You can pass around arbitrarily dimensions arrays like any another variable if you wrap them up in a struct:
#include <stdio.h>
#define n 3
struct S {
int a[n][n];
};
static struct S make_s(void)
{
struct S s;
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
s.a[i][j] = i + j;
}
return s;
}
static void print_s(struct S s)
{
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
printf(" %d", s.a[i][j]);
printf("\n");
}
}
int main(void) {
struct S s;
s = make_s();
print_s(s);
return 0;
}
You are probably declaring n as a constant integer:
const int n = 3;
Instead, you should define n as a preprocessor definition:
#define n 3

Pointer to a 2-D array

Please, I am new to C programming, please help me this.There is some error in the following code?
Basically, how do we work with pointers to 2-D arrays...
#include<stdio.h>
#include<stdlib.h>
int* max5(int** p,int r,int c)
{
/* have to design a function which takes as argument pointer to a 2-D array and returns a pointer to an array which contains the 5 highest entries*/
}
int main()
{
int rows,coloumns;
printf("Enter the number of rows and coloumns separated by a space\n");
scanf("%d %d",&rows,&coloumns);
int **ptr;
ptr=(int**)malloc(sizeof(int*)*rows);
int i,j;
for(i=0;i<rows;i++)
{
for(j=0;j<coloumns;j++)
{
scanf("%d",*(ptr+i)+j);
printf("%d\n",*(*(ptr+i)+j));
}
}
free(ptr);
return 0;
}
In C, a 2D array is simply a regular array with different indexing. So, you have two options:
Allocate an array and index it as: array[I*n+j]
Allocate an array of arrays (which is what you seem to be trying to do)
The second you can achieve in the way shown in the related post: allocate matrix in C.
Dynamically allocating a 2D array can be done in several ways.
Assuming you have a C99 compiler or C2011 compiler that supports variable-length arrays, this is dead easy:
int rows, columns;
...
scanf("%d %d",&rows,&columns);
int array[rows][columns];
array is a variable-length array (VLA), meaning its dimensions are established at run time. To pass this to another function, the prototype would simply be
int *max5( int rows, int columns, int arr[rows][columns] ) { ... }
which can also be written as
int *max5( int rows, int columns, int (*arr)[columns] ) { ... }
I'll get into that second form below. Note that both rows and columns must be declared before you use them in the VLA declaraion.
You would call it as
int *maxarr = max5( rows, columns, array );
The advantage of this approach is that a) it's easy, and b) the memory for array is allocated contiguously (i.e., as a single, continuous block of memory) and released as soon as you exit it's enclosing scope; there's no need to manually free it. The disadvantage of this approach is that rows and columns can't be arbitrarily large, you can't initialize the array using regular initializer syntax (i.e., you can't write int array[rows][columns] = { ... };), and you can't define VLAs at file scope (i.e., as a global variable). There's also the problem that VLA support has always been a little spotty, and the 2011 standard now makes them optional, so it's not guaranteed they'll be supported everywhere.
If rows or columns is very large, or if for some other reason you want to allocate this memory from the heap, it's just slightly more complicated:
int rows, columns;
...
scanf("%d %d", rows, columns);
int (*array)[columns] = malloc( sizeof *array * rows );
In this version, array is a pointer to an N-element array of int (where N == columns), and we malloc space to hold M such arrays (where M == rows). Again, this takes advantage of VLA syntax, but instead of allocating the memory from the stack frame, we allocate it from the heap. Like in the first method, the memory is allocated contiguously. You would index into it as you would any other array:
array[i][j] = x;
When you're done with the array, you would free it as
free( array );
The prototype for max5 would be
int *max5( int rows, int columns, int (*arr)[columns] ) { ... }
Look familiar? That's the second version we used earlier when we were passing a 2D VLA.
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 converted to an expression of type "pointer to T", and the value of the expression will be the address of the first element in the array.
In the first case where we declared array as a 2D VLA, when you call
int *maxarr = max5( rows, columns, array );
the expression array is converted from type "rows-element array of columns-element array of int" to "pointer to columns-element array of int", so what max5 receives is a pointer value, not an array. It just so happens that in the context of a function parameter declaration, T a[N] and T a[] are both interpreted as T *a; IOW, all three declare a as a pointer to T.
Thus, both
int *max5( int rows, int columns, int arr[rows][columns] ) { ... }
and
int *max5( int rows, int columns, int (*arr)[columns] ) { ... }
declare arr as a pointer to an array, not a 2D array. Similarly, both return a simple int *, as opposed to an array of int. The reason for this is simple; if you return a subarray using
return arr[i];
the expression arr[i] will have type "columns-element array of int"; by the rule above, that expression will be converted to type int *. C doesn't allow you to return array objects as arrays, nor can an array expression be the target of an assignment.
Now, what if you're working with a C89 compiler, or a C2011 compiler that doesn't support VLAs? In this case, you'd need to allocate the memory in a piecemeal fashion, like so:
int rows, columns;
int **array;
...
scanf("%d %d", rows, columns);
array = malloc( sizeof *array * rows );
if ( array )
{
int i;
for ( i = 0; i < rows; i++ )
{
array[i] = malloc( sizeof *array[i] * columns );
}
}
Your max5 prototype would now be
int *max5( int rows, int columns, int **arr );
You're not dealing with arrays or pointers to arrays anymore; you're dealing with a double pointer, which is not the same thing as a pointer to a 2D array. You can still subscript it as though it were a 2D array
arr[i][j] = x;
but it is not an array object in and of itself.
The most important thing to realize is that the memory is not guaranteed to be contiguous; rows may not be adjacent in memory, so you don't want to try to walk down rows using a pointer, like so:
int (*p)[columns] = arr;
while ( some_condition )
p++; // sets p to point to the next row
For an array that was allocated piecemeal, that sort of algorithm won't work.
Also, since the memory was allocated piecemeal, it needs to be freed piecemeal:
for ( i = 0; i < rows; i++ )
free(array[i]);
free( array );
Hope that helps.
this code fix your issue :
#include<stdio.h>
#include<stdlib.h>
int* max5(int** p,int r,int c)
{
/* have to design a function which takes as argument pointer to a 2-D array and returns a pointer to an array which contains the 5 highest entries*/
}
int main()
{
int rows,coloumns;
printf("Enter the number of rows and coloumns separated by a space\n");
scanf("%d %d",&rows,&coloumns);
int **ptr;
int i,j;
ptr=(int**)malloc(sizeof(int*)*rows);
for(j=0;j<coloumns;j++)
{
*(ptr+j) = (int *)malloc(sizeof(int)*coloumns);
}
for(i=0;i<rows;i++)
{
for(j=0;j<coloumns;j++)
{
scanf("%d",*(ptr+i)+j);
//*(*(ptr+j)+i) = i+j;
printf("%d\n",*(*(ptr+i)+j));
}
}
free(ptr);
return 0;
}
in fact you forget to allocate memory for columns !
You can allocate a 2D array in C by defining the type correctly:
int (*ptr)[coloumns] = calloc(sizeof(int) , rows * coloumns);
Then you can address it via ptr[i][j]. If your array does need to persist beyond the scope that allocated it and is fairly small then you can also allocate it on the stack
int ptr[rows][coloumns];
memset(ptr, 0, sizeof(ptr));
What you are trying to allocate is an array of pointers int (*)[coloumns] is not the same type as int ** although they can be both addressed through the use of the indexing operator [i][j]. The latter is a far more complicated data structure and is prone to more errors. I would advise against it unless you need variable row sizes.

Resources