Max number in array - c

I know many solutions exist for this one, but after looking around I haven't found any that involves pointers
Right now it keep throwing warnings and there's no output at all, what am I doing wrong?
#include <stdio.h>
int findbig (int a[], int n)
{
int max = a[0];
for (int i = 1; i < n; i++)
{
if (a[i] > max)
{
max = a[i];
}
}
return max;
}
int main (void)
{
int n;
printf("How many numbers? \n");
scanf("%d", &n);
int a[n];
printf("Now enter those %d numbers: \n", n);
for (int i = 1; i < n; i++)
{
scanf("%d", &a[i]);
}
int biggest = findbig (a[n], n);
printf("The biggest number is: %d\n", biggest);
return 0;
}
My compiler is complaining that:
-warning: passing argument 1 of 'findbig' makes pointer from integer without a cast [enabled by default]
-note: expected 'int *' but argument is of type 'int'

a[n] (as well as its equivalent *(a + n) form) is an int, not a pointer to int. It's also one past the boundary of your array. You need to turn your warnings into errors. You pass an int, whose value is converted to a pointer (address), which is, well, no good.
You need to call your function like so:
findbig(a, n);
Regardless of your signature, findbig receives a pointer to int. You cannot pass arrays to (or return them from) functions in C. They degrade to pointers to their first element.
On a side note, you're always skipping the first element when populating the array, so the user says "I want to enter N numbers", but you only allow them to enter n-1. The is also problematic as you use a[0] as your initial max number, but the value of that element is indeterminate.
It could be anything, i.e., some huge number, and then your function will give strange results. Either initialize the array to 0 (int a[n] = {0};) or start your loop at 0 (better).

By indexing a, doing a[n], you get the value of the array a in the n-th index, which is of int type. You need to invoke findbig(....); function using the array "pointer" variable, without indexing it, by doing:
findbig(a, n);

This line is wrong.
int a[n]
Array should be initialized with constant value, because the space of array is allocated before execution of the program. So, variables won't work.

Related

Passing pointer array to function in C

I am having trouble passing a pointer array to a function. I will post a simple example that still doesn't work for me. Could you please tell me what I am doing wrong?
#include <stdio.h>
#include <stdlib.h>
int transformare(int *v[1])
{
*v[1] = 10;
return 0;
}
int main()
{
int v[1];
printf("n = ");
scanf("%d", &v[1]);
transformare(&v);
printf("%d", v[1]);
return 0;
}
You have two problems:
Array indexes are zero-based. That is, an array of N elements have indexes from 0 to N - 1 (inclusive)
The declaration int *v[1] declares v as an array of one pointer to int, not as a pointer to an array of one int. That would be int (*v)[1]. Which is also the type of &v from the main function.
The solution to the second problem (using the correct type) then leads to a third problem, as it means that *v[0] is incorrect due to operator precedence. You need to use parentheses here too, as in (*v)[0].
However the second (and the following third) problem is moot, since you don't need to pass arrays "by reference".
Arrays naturally decays to pointers to their first element. When using plain v when a pointer to int is expected, the compiler will automatically translate it as &v[0].
That means you could declare the function to simply take an int * as argument, and simply pass plain v as the argument.
First, please note that indizes are 0-based in C, i.e. the first (and - in your case only) element is v[0].
Concerning passing it, just define the parameter as pointer to int, i.e. int*. A variable of type int[1] will decay to a pointer to int when passed to a function (so there is no need to write transformare(&v), its transformare(v).
int transformare(int *v)
{
v[0] = 10;
return 0;
}
int main()
{
int v[1];
printf("n = ");
scanf("%d", &v[0]);
transformare(v);
printf("%d", v[0]);
return 0;
}

Static or Pointer When "Returning" Array

I'm attempting to load an array of size n (user input), with random values. I've read that you can not return an array in C, you must use a pointer (Which is quite confusing). However, I've read that if you are storing that array to a local variable in the returning function, a pointer will not work and a static array can be used (can that be returned in a function?). Also, I've read that you are supposed to call free after using the array is open the space back up? I must be using it wrong because it crashed. So I commented it out for now. Some clarification would be great.
Here's what I have so far. When printing, it's just printing what I'm assuming is just garbage.
int* prefixAverages1(int);
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main() {
int choice;
int input;
printf("What is the size of the array?:");
scanf("%d", &input);
printf("Do you want to run prefixAverages 1 or 2?");
scanf("%d", &choice);
switch(choice) {
case 1:
printf("Beginning prefixAverages1\n");
int *a = prefixAverages1(input);
for (int i=0; i < input; i++) {
printf("%d", &i);
printf("%d \n", a[i]);
}
//free(a);
break;
}
}
int* prefixAverages1(int input) {
int x[input];
int *a = (int*)malloc(input);
srand(time(NULL));
for(int i = 0; i < input; i++) {
int s = 0;
for(int j = 0; j < i; j++) {
int r = rand() % 100;
x[j] = r;
s = s + x[j];
}
a[i] = s / (i+1);
printf("%d \n", a[i]);
}
return a;
}
I'm aware my syntax may be wonky. I haven't touched C in years, so let me know if my error is syntaxical.
edit: Values are printing as intended in the function. Added print statement in code for clairity
I'm attempting to load an array of size n (user input), with random
values. I've read that you can not return an array in C, you must use
a pointer (Which is quite confusing).
Yes, the relationship between pointers and arrays and the surprisingly wide scope of things you cannot do with arrays themselves are common points of confusion. To some extent it's a pedantic distinction. Almost everything C allows you to do with an array, it makes you do via a pointer, but it automatically converts values of array type to appropriate pointers, so that those details are largely hidden.
But in some places it pokes out. For example, there is no valid syntax that allows you even to try to declare a function that returns an array.
In other places it is actively misleading. For example, you can declare a function that appears to accept an array as an argument, but the standard explicitly specifies that the argument is actually a corresponding pointer (and that's what naturally falls out when you call such a function anyway). Specifically:
int foo(int x[3]);
is 100% equivalent to
int foo(int *x);
However, I've read that if you
are storing that array to a local variable in the returning function,
a pointer will not work
That's not so much about arrays specifically, but rather about automatic variables in general. These logically cease to exist when they go out of scope -- at the end of the innermost block in which they are declared -- so pointers to or into such objects are no longer valid once the function returns. One way to obtain such a pointer value is for the function to return it. That in itself is OK, but you cannot safely dereference such a pointer value.
and a static array can be used (can that be
returned in a function?).
The lifetime of static variables of any type is the whole execution of the program. Therefore, it is safe and can be meaningful to return a pointer (in)to a static variable from a function. But although it can work to return a pointer to a static array from your function, you still cannot return such an array itself.
Also, I've read that you are supposed to
call free after using the array is open the space back up?
You should free memory that you have allocated with one of the memory allocation functions (malloc() etc.), and no other. But when you allocate memory inside a function, you can give the caller responsibility for freeing that memory by returning the pointer to it, among other ways.
In fact, most of what you demonstrate in your example code is fine in those regards. However, you do make a key error that undermines your program. Here:
int *a = (int*)malloc(input);
You allocate input bytes and store the pointer to them in a, but that is not enough storage for input objects of type int. The size of an int varies from implementation to implementation, but the minimum size permitted by the standard is two bytes, in the most common size is four bytes. To allocate space for input objects of type int, the basic idiom is
int *a = malloc(input * sizeof(int));
Personally, though, I prefer
int *a = malloc(input * sizeof(*a));
because then I get the correct size no matter what type the pointer's referenced type is, and even if I change it later.
The fact that you treated the allocated space as if it were larger than it really was likely explains much of your program's misbehavior, including the crash when you tried to free the allocated memory.
First of all malloc takes an inparam of no of bytes not absolute array size - so change this line:-
int *a = (int*)malloc(input);
to
int *a = malloc(input*sizeof(int));
Secondly, to debug incorrect values being printed put a print in your function prefixAverages1 :-
...
...
a[i] = s / (i+1);
printf("%d \n", a[i]);
...
In main print, get rid of the first print.. this is probably making you think printing incorrect values.. The address of the local loop counter variable will look like garbage
printf("%d", &i);
OR if you wanted to track the indexes of the array elements as well modify it to :-
printf("%d", i);
You must introduce the free back to avoid leaking memory
And you should follow #AustinStephens's suggestion and avoid using a second function
This works as far as having a function that loads an array with random values:
void randomValues(int arr[], int size);
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main() {
int i;
int input;
int *array;
printf("What is the size of the array?: ");
scanf("%d", &input);
array = malloc(sizeof(int) * input);
randomValues(array, input);
for(i = 0; i < input; ++i)
printf("array[%d] = %d\n", i, array[i]);
free(array);
return 0;
}
void randomValues(int arr[], int size) {
int i;
int r;
srand((int) time(0));
for(i = 0; i < size; ++i) {
r = rand() % 100;
arr[i] = r;
}
}

Finding Determinant of a matrix in C

This is the C code for determinant of matrix, But it gives compilation errors.
Code is:
#include<stdio.h>
#include<math.h>
int m;
float determinant(float b[][]);
int main(void)
{
int i,j,m;
printf("enter a no: ");
scanf("%d",&m);
//printf("%d",m);
float arr[m][m];
for(i=0;i<m;i++)
{
for(j=0;j<m;j++)
{
scanf("%f",&arr[i][j]);
//printf("%f",arr[i][j]);
}
}
for(i=0;i<m;i++)
{
for(j=0;j<m;j++)
{
printf("%f ",arr[i][j]);
}
printf("\n");
}
float det = determinant(arr);
printf("Determinant= %f ", det);
}
float determinant(float b[][])
{
int i,j;
int p;
float sum = 0;
float c[m][m];
for(i=0;i<m;i++)
{
for(j=0;j<m;j++)
{
printf("%f ",b[i][j]);
}
printf("\n");
}
if(m==2)
{
printf("Determinant for m=2");
sum = b[0][0]*b[1][1] - b[0][1]*b[1][0];
return sum;
}
for(p=0;p<m;p++)
{
int h = 0,k = 0;
for(i=1;i<m;i++)
{
for( j=0;j<m;j++)
{
if(j==p)
continue;
c[h][k] = b[i][j];
k++;
if(k == m-1)
{
h++;
k = 0;
}
}
}
m=m-1;
sum = sum + b[0][p]*pow(-1,p) * determinant(c);
}
return sum;
}
And the Compilation Errors are:
det.c:5:25: error: array type has incomplete element type
det.c: In function ‘main’:
det.c:36:2: error: type of formal parameter 1 is incomplete
det.c: At top level:
det.c:45:25: error: array type has incomplete element type
det.c: In function ‘determinant’:
det.c:91:3: error: type of formal parameter 1 is incomplete
det.c:99: confused by earlier errors, bailing out
Preprocessed source stored into /tmp/cc1Kp9KD.out file, please attach this to your bug report.
I think the error is in the passing of 2-D Array. when I passing it as a pointer then it gives warnings but no errors but it does not give the right result as in always gives determinant as Zero. So I guess the array is not being passed only and when I print it in the function determinant it doesn't print also.
Please help as I am stuck because of this in my project.
in your code,
scanf("%d",&m);
//printf("%d",m);
float arr[m][m];
here arr is a 2D array with static memory allocation so you can not read m at run time and declare arr like this.
so if you are want to define the array dynamically then use dynamic memory allocation methods like malloc() in C.
When you declare the prototype of a function as
int foo(int arr[], int n);
then compiler interprets it as
int foo(int (*arr), int n); // and that's why you can omit the first dimension!
i.e, your function is expecting first argument is of type int *. Similarly, when the parameter is a multidimensional array as
int foo(int arr[][col], int n); // Only first dimension can be omitted. You need to specify the second dimension.
then the compiler interprets it as
int foo(int (*arr)[col], int n);
i.e, your function is expecting first argument is of type int (*)[col] (a pointer to int array).
Since when passed to a function (in most cases) array names decay to pointer to its first element, in your case arr will be decayed to pointer to its first element, i.e, first row. Hence its type will become float (*)[m]. Its is compatible to your function parameter if you will declare it as
float determinant(int m, float b[][m]);
and the call should be like
float det = determinant(m, arr);
You can declare array dynamically like this in C99 (variable length arrays, pointed out by haccks), but not in the earlier version:
float arr[m][m];
So, if it troubles you then instead declare a pointer and malloc memory for it:
float* arr = malloc(sizeof(float)*m*m);
Also, the definition won't work (in either case):
float determinant(float b[][]);
you need to define the columns in the array that you pass to the function.
If you declare and allocate the pointer as I have shown then you can just pass a pointer in your function:
float determinant(float *b, int size); //here size is your row dimension, in this case equal to m
And inside the function, access your elements like:
*(b + size*i + j) = value // equivalent to b[i][j];
Declare your array with explicit bounds float b[m][m]; the compiler doesn't understand empty bounds in float b[][] (empty bounds are OK only for 1-D arrays, for reasons explained in the other answers).
So your determinant function should look like this:
float determinant(int m, float b[m][m])
{
...
}
There are other ways to make your code work, but I think this way is closest to what you already have.
I agree you can't move with this syntax of array initialization, u could have used
int *p=(int*)calloc(n*n,sizeof(float));
And then access your elements as :-
*(p+j+n*i);//for p[i][j] element
Hope it helps :)

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.

Passing an array of arrays in C

I need to have a function which takes a 2D array and generates random bits, so the result is an array of random binary strings.
I have the following code,
#define pop_size 50
#define chrom_length 50
main() {
int population[pop_size][chrom_length];
init_pop(&population);
}
int init_pop(int *population[][]) {
for(i = 0; i < pop_size; i++) {
for(j = 0; j < chrom_length; j++) {
*population[i][j] = rand() % 2;
}
}
return 0;
}
On compilation, I am getting the following error message:
array type has incomplete element type
Any suggestions?
Time for the usual spiel...
When an array expression appears in most contexts, its type is implicitly converted from "N-element array of T" to "pointer to T", and its value is set to point to the first element of the array. The exceptions to this rule are when the array expression is an operand of either sizeof or the unary & operators, or if it is a string literal being used as an initializer in a declaration.
What does all that mean in the context of your code?
The type of the expression population is "pop_size-element array of chrome_length-element arrays of int". Going by the rule above, in most contexts the expression population will implicitly be converted to type "pointer to chrome_length-element arrays of int", or int (*)[chrome_length].
The type of the expression &population, however, is "pointer to pop_size-element array of chrome_length-element arrays of int", or int (*)[pop_length][chrome_size], since population is an operand of the unary & operator.
Note that the two expressions have the same value (the address of the first element of the array), but different types.
Based on the code you've written, where you call the function as
init_pop(&population);
the corresponding function definition should be
int init_pop(int (*population)[pop_size][chrome_length]) // note that both dimensions
// must be specified
and you would access each element as
(*population)[i][j] = initial_value;
Note that this means init_pop can only deal with pop_size x chrome_length arrays; you can't use it on arrays of different sizes.
If you call the function as
init_pop(population); // note no & operator
then the corresponding function definition would have to be
int init_pop(int (*population)[chrome_length]) // or population[][chrome_length],
// which is equivalent
and you would access each element as
population[i][j] = initial_value;
Note that you don't have to dereference population explicitly in this case. Now you can deal with arrays that have different population sizes, but you're still stuck with fixed chromosome lengths.
A third approach is to explicitly pass a pointer to the first element of the array as a simple pointer to int and treat it as a 1D array, manually computing the offsets based on the array dimensions (passed as separate parameters):
init_pop(&population[0][0], pop_size, chrome_length);
...
int init_pop(int *population, size_t pop_size, size_t chrome_length)
{
size_t i, j;
...
population[i*chrome_length+j] = initial_value;
...
}
Now init_pop can be used on 2D arrays of int of different sizes:
int pop1[10][10];
int pop2[15][20];
int pop3[100][10];
...
init_pop(&pop1[0][0], 10, 10);
init_pop(&pop2[0][0], 15, 20);
init_pop(&pop3[0][0], 100, 10);
...
EDIT: Note that the above trick only works with contiguously allocated 2D arrays; it won't work with dynamically allocated arrays where the major dimension and the minor dimensions are allocated separately.
Here's a handy table, assuming a definition of int a[N][M]:
Expression Type Implicitly converted to
---------- ---- -----------------------
a int [N][M] int (*)[M]
a[i] int [M] int *
a[i][j] int
&a int (*)[N][M]
You need to tell the compiler all dimensions except the first, when passing arrays as arguments:
int init_pop(int population[][pop_size])
{
...
}
Yes, this means it's hard to make it completely dynamic and introduces a place where you have to repeat yourself.
UPDATE: I was confused, and had the requirement inverted. Fixed now.
For multidimensional arrays in C/C++ you have to specify all dimensions except the first.I am modifying your program to make it work correctly:
#include <stdio.h>
#include <stdlib.h>
#define pop_size 3
#define chrom_length 3
void init_pop(int population[][chrom_length]) {
int i,j;
for(i = 0; i < pop_size; i++) {
for(j = 0; j < chrom_length; j++) {
population[i][j] = rand() % 2;
}
}
}
/* For Checking */
void display (int population[][chrom_length]){
int i,j;
for(i = 0; i < pop_size; i++) {
for(j = 0; j < chrom_length; j++) {
printf("%d ",population[i][j]);
}
printf("\n");
}
}
int main(void) {
int population[pop_size][chrom_length];
init_pop(population);
display(population); /* For Checking */
return 0;
}
If you not going to use global constants here is the correct way of doing it.
This is the problem:
int *population[][]
A multidimensional array is simply a block of continuous memory, and when you say foo[3][2], the compiler finds the right index by 3*last_dimension_size + 2, which means that it has to know the size of all the dimensions except the last one.
So that declaration is an error.
BTW-- There are several very complete discussion of issues related to multidimensional arrays in c already on SO. Try searching under both or either [c] and [c++]

Resources