Finding largest element in an array in C [duplicate] - c

This question already has an answer here:
Definitive List of Common Reasons for Segmentation Faults
(1 answer)
Closed 5 years ago.
My program need to have a function in which it finds the largest element of an array. It then returns the position of largest element. However, when finding the largest element, I am only allowed to use pointer arithmetic.
#include <stdio.h>
int *largest(int *array, int size){
int *p1 = array;
int *count, max = *p1;
for(*count = 0; count < p1 + size - 1; p1++){
if (max < *p1){
max = *p1;
count++;
}
}
return count;
}
int main(void){
int *array, size = 10;
printf("enter elements; ");
for(int i = 0; i < size; i++){
scanf("%d ", &array);
array++;
}
printf("\nThe largest element in the array is in element %d", *largest(array, size));
}
However, when I run the program, after enter values for the elements, it gives me:
segmentation fault (core dumped)

Mistakes in the function main:
You didn't allocate memory for the array. You need to add line array = (int*) malloc(sizeof(int) * size);. Without this line you get segmentation fault.
Another mistake is in filling array. Array is pointer already so you don't have to reference it again. Now you are changing pointer, not array values
Potential bug: In loop when you fill array, you increase pointer, so you loose information about beginning of array. You can get it again after loop doing array = array - size;, but it won't work if you break loop earlier. It is better to work with temporary pointer.
Mistakes in the function largest:
You created pointer count, which is not allocated and then in for loop initialization you write value 0 to unknown address. Causes segmentation fault.
In for loop you are trying to read memory from address 0 to address array + size - 2, but you want to read it from beginning of array to the end of array which is from array to array + size - 1.
Returning count makes no sense, but to sum it up, look at the example.
Pointer is just number which is address to memory, so when you don't allocate it or don't assign existing pointer, then it points randomly to memory and OS don't let you access that memory. It can happen that you will read something from random pointer, but new compilers sets initial value to 0. In BSD you can read from address 0, but linux cause segmentation fault (I hope that I didn't switch it). Writing to address 0 causes segmentation fault in both systems.
You should also check in function if you got valid pointer and allocation can fail so you need to check pointer immediatelly after allocation too. To sum this: Never trust pointer, always check it's validity.
Example doesn't check validity of pointers.
#include <stdio.h>
int *largest(int *array, int size){
int *end = array + size; // address behind array
int *max = *array; // address with largest value
for(; array < end; ++array){ // you dont need initialization since the array points to beginning
if (*max < *array){ // compare values, not address
max = array; // save position of pointer with largest value
}
}
return max; // return address with largest value
}
int main(void){
int *array, size = 10;
array = (int*)malloc(sizeof(int) * size); // allocate memory
printf("enter elements; ");
int *tmp = array; // temporary variable to not loose information about beginning of array
for(int i = 0; i < size; i++){
scanf("%d ", tmp); // reference is not needed since tmp is already pointer to value
tmp++;
}
printf("\nThe largest element in the array is in element %d", *largest(array, size));
}

Related

Array of pointers whose elements point to another array of pointers

What I need very precisely is an array A[10] and each of its element pointing to the respective element of array B[10] whose each element store its index.
Hence, A[1] points to B[1] and B[1] has value of 1.
So, when I call *A[1] or *B[1], I get 1.
I know it can be super easy if the array B[10] is not an array of pointers but of integers but I need this for another purpose.
This is what I did but segmentation fault was offered.
#include <stdio.h>
int main() {
int *A[10];
int *B[10];
for(int i=0; i<10; i++) {
A[i] = B[i];
*B[i] = i;
printf("\n%d %d",*A[i],*B[i]);
}
}
By the way, I am not very proficient in pointers.
Your commented code :
int main() {
int *A[10]; // an array of 10 pointers, each of them pointing nowhere
int *B[10]; // an array of 10 pointers, each of them pointing nowhere
// now each array a and b contain 10 uninitialized pointers,
// they contain ideterminate values and they point nowhere
for(int i=0; i<10; i++) {
A[i] = B[i]; // copy an uninitialized pointer
// this usually works but it's pointless
*B[i] = i; // you assign i to the int pointed by *B[i]
// but as *B[i] points nowhere you end up with a segfault
printf("\n%d %d",*A[i],*B[i]); // you never get here because the previous
// line terminates the program with a segfault,
// but you'd get a segfault here too for
// the same reason
}
}
Your program is basically equivalent to this:
int main() {
int *a; // a is not initialized, it points nowhere
*a = 1; // probably you'll get a segfault here
}
Accessing the thing pointed by a pointer is called dereferencing the pointer. Dereferencing an uninitialized pointer results in undefined behaviour (google that term), most likely you'll get a seg fault.
I'm not sure what you're trying to achieve, but you probably want something like this:
#include <stdio.h>
int main() {
int* A[10];
int B[10];
for (int i = 0; i < 10; i++) {
A[i] = &B[i];
B[i] = i;
printf("%d %d\n", *A[i], B[i]);
}
}

getting C segmentation fault 11

I was given the assignment of writing a C code which contains a function, which when passed through an array of length n returns a pointer to the array’s largest element. In order to make it easy for us, the length n was set to 10.
I wrote the code below and compiled it and it didn't show any error. Then, I ran this code and it asked for the 10 inputs for the array, but instead of returning the pointer with the largest element, it read segmentation fault 11.
I am new to pointers, and so could not figure out what exactly went wrong. Any help will be greatly appreciated.
#include<stdio.h>
#define N 10
int *find_largest(int a[], int n)
{
int i;
int *max;
*max = a[0];
for(i = 1; i < n; i++)
{
if(a[i] > *max)
*max = a[i];
}
return max;
// this function returns the pointer with the max. value
}
int main(void)
{
int b[N], i;
int *p;
printf("Enter %d numbers: ", N);
for(i = 0; i < N; i++)
scanf("%d", &b[i]);
//scans all the inputs
p = find_largest(b, N);
//p gets assigned the value of the max valued pointer
printf("largest element: %d", *p);
return 0;
}
Edit- After looking at the wonderful advices given, I modified my code a bit. I changed *max=a[0] to max= &a[0], and *max=a[i] to max=&a[i]. Now, the code runs without any error, but instead of returning the pointer with the largest value, it returns the largest input instead.
In this line, you write to the place the uninitialised ponter is pointing to.
*max = a[0];
This causes undefined behaviour (or "UB", reading up on it is worth the time) and to be strictly avoided; among other reasons because it is a very likely reason for segfaults.
What you probably want to do is to write the address of the first element into the pointer.
max = &a[0];
Later you write the place the pointer is pointing to, updating it to the max value you have found.
*max = a[i];
Guessing from the rest of your code, you probably want to just keep the address of the max element, so that you can return its address as it is in the input array, without changing the values in the input array (which your currently do, and it seems unlikely that you intend to...).
max = &a[i];
Referring to your comment (that the value is returned, not the pointer):
For returning a pointer (not a value), make sure that you
return max; // the pointer, not the value it is pointing to
Which is what you actually do in the currently shown code version (possibly before an edit...).
Do not return *max; that would return the value.
If by "return" you mean "print", then you need to change the
printf("largest element: %d", *p);
Use p instead of *p and change the format specifier accordingly.
You probably want "largest element at address: %p". (Compare http://en.cppreference.com/w/c/io/fprintf )
printf("largest element at address: %p", p);
int *max;
*max = a[0];
This is UB (undefined behavior) since max is not pointing to valid memory and you try to dereference it.
max = &a[0];
Moreover your logic to find the max is wrong. Why do you reset it every time to 0th element. It should be something like.
for(i = 1; i < n; i++)
{
if(a[i] > *max)
max = &a[i];
}

Get size of a simulated array using malloc

I have a simulated 2D array using pointers with malloc and I want to get the size of that array, since sizeof() returns me the size of the pointer.
My code (ANSI C):
void main(){
int s1=10;
int s2=15;
int ** rack=(int**)malloc(s1*sizeof(int**));
for(int i=0; i<s1; i++) rack[i]=(int*)malloc(s2*sizeof(int*));
}
I want a function (may by system, may do it myself) this way:
size(rack) //returns 10
size(rack[0]) //returns 15
Thanks in advance! (For more info I use GNU/Linux)
First of all, the way you allocate memory for your 2D array is wrong. You need to change it to :
void main(){
int s1 = 10;
int s2 = 15;
int** rack = malloc(s1*sizeof(int*));
if (rack == NULL)
return;
for(int i=0; i<s1; i++) {
rack[i]=malloc(s2*sizeof(int));
if (rack[i] == NULL)
return;
}
...
free(rack);
return;
}
Remember to always check malloc's result and also not to cast malloc's result.
In order to get your array's size, you can print s1*s2*sizeof(int) as you have allocated s1 pointers to int, each of which holds s2 ints.

Trouble with using calloc with an array and returning a pointer

As a reference this is the second part of my assignment:
int* generateFibonacci(int size);
This function will take as input an integer called size. The value contained in the size variable
will represent how many numbers in the Fibonacci sequence to put into the array. The function
will use calloc to create the array of this size and then fill the array with size numbers from the
Fibonacci sequence, starting with 1 and 1. When the array is complete the function will return a
pointer to it.
My trouble come in play when I get the error in line 8 "warning: assignment makes and integer from pointer without a cast".
Another error I get is in line 19 "warning: return makes pointer from integer without a cast".
So my question is, how am I suppose to set up calloc to make the array with a size from a user, then return a pointer to it?
#include <stdio.h>
#include <stdlib.h>
int* generateFibonacci(int size)
{
int i, array[size];
array[size]=(int*)calloc(size, sizeof(int));
array[0]=0;
array[1]=1;
for(i = 2; i < size+1; i++)
array[i] = array[i-2] + array[i-1];
return *array;
}
void printHistogram (int array[], int size)
{
int i, j;
for(i=0; i <= size; ++i)
{
for(j=0; j < array[i]; j++)
{
printf("*");
}
printf("\n");
}
}
int main(void)
{
int array[100], size;
printf("how big will your Fibionacci number be? ");
scanf("%i", &size);
generateFibonacci(size);
printHistogram(array, size);
return 0;
}
how am I suppose to set up calloc to make the array with a size from a user, then return a pointer to it?
For a 1D array of int * Use printf() and scanf()
int *array = {0}; //Note, leaving this initialization method for posterity
//(See related comments below.)
//however agreeing with commentator that the more idiomatic
//way to initialize would be: int *array = NULL;
size_t size = 0;
printf("Enter order of array");
scanf("%d", &size);
array = malloc(size);//create memory with space for "size" elements
if(array){//do other stuff}
But it is unclear from your example, and the comment if you really intend using a 2D array....
As stated in the comments, You have created an int array, then attempted to create memory for it.
int i, array[size];
...
array[size]=(int*)calloc(size, sizeof(int));//wrong
As it is created, array does not need memory. Memory is created on the stack as automatic.
If you wanted a 2D array of int. Then you could do it like this:
int *array[size]; //create a pointer to int []
With this, you can create an array of arrays (in concept) in this way:
for(i=0;i<size;i++) array[i]= calloc(size, sizeof(int));//do not cast the output, not necessary
Now, you essentially have a size x size 2D array of int. It can be assigned values in this manner:
for(i=0;i<size;i++)
for(j=0;j<size;j++)
array[i][j]=i*j;//or some more useful assignment
By the way, adjust the parameters of the calloc() statement as needed, but note, casting its output is not necessary.
Regarding the return statement, your function is prototyped to return a int *.
int* generateFibonacci(int size){...} //requires a return of int *
If you decide to use a 1D array, i.e. int *array={0} (requiring that you allocate memory), then return:
return array;//array is already a `int *`, just return it.
If you are using the 2D array, then to return a int *, you must decide which of the size elements of the array you want to return:
return array[i];//where `i` can be any index value, from 0 to size-1

double free() error after swapping rows of a matrix

I'm getting the double free or corruption error upon executing my code. Essentially, I am just creating a matrix in C (of any RxC dimension, which is why pointers are used), swapping two rows, printing the results, and then attempting to free the memory. When I do not swap the rows, the freeing works perfectly. When I do, it crashes. I've attempted to alter the way the swapping works to no avail. I think it has something to do with the temporary pointer for swapping going out of scope, but I'm not sure if this is the problem and how I would fix it.
MatElement is just a double.
typedef double MatElement;
main:
int main(int argc, char *argv[]) {
MatElement** matrix = matrixAlloc(3,3);
int i;
int j;
for(i = 0; i < 3; i++) {
for(j = 0; j < 3; j++) {
matrix[i][j] = i+j;
}
}
matrixPrint(matrix, "%5.1f", 3, 3);
swapRows(matrix, 0, 2);
matrixPrint(matrix, "%5.1f", 3, 3);
matrixFree(matrix);
return 0;
}
The way the matrices are allocated:
MatElement **matrixAlloc(int nr, int nc) {
int i;
MatElement *ptr;
MatElement **A;
A = malloc(nr * sizeof(MatElement *)); /* array of ptrs */
ptr = calloc(nr * nc, sizeof(MatElement)); /* matrix elements */
for (i = 0; i < nr; i++) /* set row pointers properly */
A[i] = ptr + nc * i;
return A;
}
The way they are freed:
void matrixFree(MatElement **A) {
free(A[0]);
free(A);
}
The way their rows are swapped:
void swapRows(MatElement** G, int pivotRow, int rowExamined) {
MatElement* temp;
temp = G[rowExamined];
G[rowExamined] = G[pivotRow];
G[pivotRow] = temp;
}
Does anyone have any idea about what would be causing this double free() / invalid free()?
At some point, you are swapping the first row of the matrix into another position, so the free(A[0]) in matrixFree() is attempting to free a pointer into the middle of the array, instead of the pointer returned by calloc(). You will need to save that original pointer somewhere so that you can pass it, unmolested, to free().
Your matrix looks like this way :
A has all the pointers to the first element of all the rows. So initially, A[0] points to 0th row, A[1] to 1st row and so on.
So, when you are trying to free the matrix, you know that A[0] points to first row. But at that time you are assuming that your matrix elements are in continuous position and A[0] will always point to initial pointer returned by calloc. But when you swap some rows (specially the 0th with any of other row), then A[0] doesnt point to pointer returned by calloc.
possible solution involves like allocating one more memory slot in A like :
A = malloc( ((nr+1) * sizeof(MatElement )); / array of ptrs */
and then storing original pointer returned by calloc to A[nr].
So, A[nr] will also point to calloc returned pointer.

Resources