I am trying to understand how malloc works. I did a program searches for the largest element in a one dimensional array int.
This is the code.
#include <stdlib.h>
#include <stdio.h>
void largest_element(int *nbr)
{
int i;
int n;
int m;
i = 1;
nbr = (int*)malloc(sizeof(nbr) + 8);
while (i < 8)
{
if (*nbr < *(nbr + i))
*nbr = *(nbr + i);
i++;
}
printf("%d ", *nbr);
}
int main(void)
{
int i;
int tab[8] = {11, 2, 4, 5, 9, 7, 8, 1};
int n = sizeof(tab)/sizeof(int);
i = 0;
largest_element(&tab[8]);
return(0);
}
The program works without malloc but how can I make it work with malloc? What did I do wrong and why does my code only give me garbage numbers?
I think you are lost with pointers and arrays so you can not understand malloc properly (no offense, everyone who is learning C do the same mistake).
Let's take your main function. When you run:
int tab[8] = {11, 2, 4, 5, 9, 7, 8, 1};
You staticly allocate an array of 8 integers and you fill it with your numbers.
The dynamic equivalent would be:
int* tab = malloc(sizeof(int) * 8);
tab[0] = 11;
tab[1] = 2;
/// Etc...
tab[7] = 1;
First thing: the first element of an array has the index 0. So in your largest_element function, i should be initialized at 0 instead of 1.
The reason is, when you deal with array, you deal with pointers. In your case, tab is a pointer to the first element of the array. So, when you do tab[3], you get the forth element of your array.
Second thing: when you do:
largest_element(&tab[8]);
You send to your function the eighth element after the begining of your array. The problem is: you do not own this memory area! You own the memory only until tab[7].
If you want to send the complete array to your function, just use:
largest_element(tab);
Now, let's talk about your largest_element function.
You do not need to call malloc here since the memory is already allocated
When you do *nbr = *(nbr + i); you change the value of the first element of your array. I think you wanted to do m = *(nbr + i); isn't it.
Why do you not use the nbr[i] instead of *(nbr + i)?
A correct implementation of this function would be something like (not tested):
void largest_element(int *nbr)
{
int i = 0;
int max = 0;
while (i < 8)
{
if (max < nbr[i])
max = nbr[i];
i++;
}
printf("%d ", m);
}
A last thing, using malloc involve using the function free to release the memory when you do not need it anymore.
What did I do wrong and why does my code only give me garbage numbers??
In largest_element(int *nbr) nbr points to the array tab in main (at least if you call it like this: largest_element(tab); instead of like this largest_element(&tab[8]);
Then you call nbr = (int*)malloc(sizeof(nbr) + 8); now nbr points to some allocated memory which has not been initialized and which contains garbage values. Now if you read from that memory it's normal that you get garbage values.
You simply don't need malloc for this problem, just as you don't need floating point math or file system related functions for this problem.
Related
int squaring_function (int *array, int i);
int main()
{
int array[5];
int i;
for(i=0; (i <= 5) ; i++)
{
array[i] = i;
printf("\nArray value %d is %d",i,array[i]);
}
for(i=0; (i <= 5) ; i++)
{
array[i] = (squaring_function(array, i));
printf("\nSquared array value %d is %d",i,array[i]);
}
return 0;
}
int squaring_function (int *array, int i)
{
return pow((array[i]),2);
}
I'm trying to use this squaring_function to square each value in turn in my array (containing integers 0 to 5). It seems to work however the last value (which should be 5)^2 is not coming up as 25. cmd window
I have tried reducing the array size to 5 (so the last value is 4) however this prints an incorrect number also.
I'm quite new to C and don't understand why this last value is failing.
I'm aware I could do this without a separate function however I'd quite like to learn why this isn't working.
Any help would be much appreciated.
Thanks,
Dan.
There are 2 bugs in your code. First is that you're accessing array out of bounds. The memory rule is that with n elements the indices must be smaller than n, hence < 5, not <= 5. And if you want to count up to 5, then you must declare
int array[6];
The other problem is that your code calculates pow(5, 2) as 24.99999999 which gets truncated to 24. The number 24 went to the memory location immediately after array overwriting i; which then lead to array[i] evaluating to array[24] which happened to be all zeroes.
Use array[i] * array[i] instead of pow to ensure that the calculation is done with integers.
The code
int array[5];
for(int i=0; (i <= 5) ; i++)
exceeds array bounds and introduces undefined behaviour. Note that 0..5 are actually 6 values, not 5. If you though see some "meaningful" output, well - good or bad luck - it's just the result of undefined behaviour, which can be everything (including sometimes meaningful values).
Your array isn't big enough to hold all the values.
An array of size 5 has indexes from 0 - 4. So array[5] is off the end of the array. Reading or writing past the end of an array invokes undefined behavior.
Increase the size of the array to 6 to fit the values you want.
int array[6];
The other answers show the flaws in the posted code.
If your goal is to square each element of an array, you can either write a function which square a value
void square(int *x)
{
*x *= *x;
}
and apply it to every element of an array or write a function which takes an entire array as an input and perform that transformation:
void square_array(int size, int arr[size])
{
for (int i = 0; i < size; ++i)
{
arr[i] *= arr[i];
}
}
// ... where given an array like
int nums[5] = {1, 2, 3, 4, 5};
// you can call it like this
square_array(5, nums); // -> {1, 4, 9, 16, 25}
I wrote two functions and call the functions in main.
Function 1 – I wrote a function that returns void and takes an int * (pointer to integer array) or int[], and int (for the size). The function needs to initialize all the elements of the array to non-zero values.
Function 2 – I wrote another function that returns int and takes an const int * (pointer to integer array) or int[], and int (for the size). The function should sum all the elements of the array and return the sum.
In main I defined an integer array of size 5. Called function 1 in main to initialize the values of the array. Called function 2 in main to get the sum and print the value of the sum to the console.
My problem is the program runs but the print out for sum we are getting is a large (in the millions), random, number and is not the expected answer of 15. Anyone who can help us get the correct answer would be greatly appreciated
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#pragma warning(disable: 4996)
void func1(int* ptr, int size);
int func2(const int* ptr, int size);
int main()
{
int grid[5];
func1(grid, 5);
func2(grid, 5);
}
void func1(int* ptr, int size)
{
*ptr = 1, 2, 3, 4, 5;
}
int func2(const int* ptr, int size)
{
int sum;
sum = ptr[0] + ptr[1] + ptr[2] + ptr[3] + ptr[4]; // *(ptr + 0); putting an asterisk makes it so that it changes the entire "ptr" value and the "[0]" value
printf("\n\nThe sum of the integers in the array is %d.\n\n", &sum);
}
*ptr = 1, 2, 3, 4, 5;
does not do what you think it does. It actually evaluates all the integer constants but sets ptr[0] to be 1 (see comma operator for more detail), leaving all the others at some arbitrary value.
Note that it is not evaluating *ptr = (1, 2, 3, 4, 5) (which would set *ptr to 5) but is actually evaluating (*ptr = 1), 2, 3, 4, 5 - this works because something like 42 is actually a valid C statement, albeit not very useful.
If you're trying to set the array to increasing values, just use something like:
for (int i = 0; i < size; i++)
ptr[i] = i + 1;
You probably also want to do that when summing the values since it should depend on the passed-in size rather than just summing five values:
int sum = 0;
for (int i = 0; i < size; i++)
sum += ptr[i];
Additionally, the value you are printing out is not the sum, it's the address of the variable containing the sum (a decent compiler will warn you about this). You should be using sum in your printf rather than &sum.
And, as a final note, the signature for func2 indicates that you should actually be returning the sum rather than just printing it. So I would suggest removing the printf from that function and simply doing:
return sum;
Then you can put the printf into the caller (main) as follows:
int main(void)
{
int grid[5];
func1(grid, sizeof(grid) / sizeof(*grid));
int sum = func2(grid, sizeof(grid) / sizeof(*grid));
printf("The sum of the integers in the array is %d.\n\n", sum);
return 0;
}
Note the use of sizeof(grid) / sizeof(*grid), which is basically the number of array elements in grid - this will allow you to resize grid by simply changing it in one place to something like int grid[42] and still have all the code work with the updated size.
Not actually necessary for your code but it's best to get into good programming habits early (more descriptive names for your functions may also be a good idea).
Line *ptr = 1, 2, 3, 4, 5; assigns ptr[0] value and leaves other spots unitilized so when you sum it, it will be random memory.
You should use for like this to initialize
for(int i=0;i<size;i++)
{
ptr[i] = i+1;
}
and similiar aproach to sum it.
I'm fairly new to C and I'm working on a project. Given an integer array, I want to move all the zeros in it to the left of the array with the rest of the elements in any order to the right of all the zeros. The basic idea of my algorithm is to count the number of zeros in the array, create a new array with the number of zeros in it from the old array, and then "append" the rest of the non-zero integers onto this array. And then of course I print finished product.
int main(int argc, const char * argv[]) {
int a[10] = {3, 0, 1, 4, 0, 0, 7, 20, 1, 5};
int n = 10, count = 0;
// counts the number of 0's in the original array
for (int i = 0; i < n; ++i)
{
if (a[i] == 0)
{
++count;
}
}
// creates a new array and makes each element 0
int *array = NULL;
for (int j = 0; j < count; ++j)
{
array = realloc(array, (j + 1) * sizeof(int));
array[j] = 0;
}
// adds the nonzero elements of the array to the new array
for (int l = count; l < n; ++l)
{
array = realloc(array, l * sizeof(int)); // getting an error here
if (a[l] != 0)
{
array[l+count] = a[l];
}
}
// prints the array out in a nice format
printf("%s", "{");
for (int k = 0; k < n-1; ++k)
{
printf("%d%s", array[k], ",");
}
printf("%d", array[n-1]);
printf("%s", "}\n");
free(array);
return 0;
}
I'm getting a "Thread 1: EXC_BAD_ACCESS (code=1, address=0x40)" error when I run this code. I think it's got to do something with invalid pointers to the new array, but I'm not sure how to fix it.
array[l+count] = a[l];
This accesses the memory block that array points at beyond its allocated size. You have to do it differently, using a second index:
// adds the nonzero elements of the array to the new array
int l = count;
for (int j=0; j < n; ++j)
{
if (a[j] != 0)
{
array = realloc(array, (l+1) * sizeof(int));
array[l] = a[j];
++l;
}
}
About your algorithm:
I think u don't need to create a new array, just use a int tmp as swap area, and a int foundZeroCount as index, u swap 2 numbers at a time.
About memory allocation:
If u want to allocate memory for a fixed size array, just use malloc() to allocate array once, later when u need to extend the array, just call realloc() once.
About memory reset:
Just use memset(), and don't need a loop.
Suggestion - about c programming
Try improve your c basic, especially about array / pointer / memory, and try to know more functions from glibc.
Books like <The c programming language 2nd>, GNU c library document, and <The linux programming interface> would be useful, I guess.
The problem is with array[l+count] = a[l]; right when you are done allocating your 'zero-array' it's size is 3 and then you try to access (l + count)'th position which is 6.
And even if you have fixed those issues with memory it still wouldn't work because a[l] and further may still be zeros. (Your initial array is doesn't have zeroes in the beggining, remember?)
And there is a couple of suggestions:
use calloc() to build your initial array of zeros because as man states:
The calloc() function allocates memory for an array of nmemb elements
of size bytes each and returns a pointer to the allocated memory. The
memory is set to zero
First allocate then set because operations with memory are quite taxing for performance. It would be better for you to first allocate some memory and work with it instead of reallocating it each step. It would be much easier to keep track of as well.
Other answers address your immediate issue, that
array[l+count] = a[l];
attempts to access outside the bounds of the allocated space to which array points. I'll focus instead on your approach to the problem, which is flawed.
Dynamic memory allocation is comparatively expensive. You do not want to do any more than necessary, and it is particularly poor form to reallocate many times to increase by small increments each time, as you do.
Since you know at compile time how many elements you will need, dynamic allocation is altogether unnecessary here. You could instead do this:
int a[10] = {3, 0, 1, 4, 0, 0, 7, 20, 1, 5};
int array[10] = { 0 };
(Note also here that when an array initializer is provided, any array elements it does not explicitly initialize are initialized to 0.)
Even if you did not know at compile time how many elements you would need, it would be far better to perform the whole allocation in one chunk. Moreover, if you did that via calloc() then you would get automatic initialization of the allocated space to all-zeroes.
The count is known before defining the array. You can allocate memory using malloc as shown below.
array = malloc( count * sizeof(int)).
The error indicates you are trying to access address 0x40. This indicates one of the pointer has become NULL and you are trying to dereference ptr+0x40.
Before you start to hack away, take your time to consider the actual problem, which you have described as:
count the number of zeros in the array, create a new array with the number of zeros in it from the old array, and then "append" the rest of the non-zero integers onto this array.
Your comments say what the code should do, yet the code does something entirely different. Your algorithm to solve the problem is wrong - this, and nothing else, is the cause of the bugs.
To begin with, if the new array should contain all zeroes of the old array plus all non-zeroes, then common sense says that the new array will always have the same size as the old array. You don't even need to use dynamic memory allocation.
The code you have creates a new array and discards the old one, in the same memory location, over and over. This doesn't make any sense. On top of that, it is very ineffective to call realloc repeatedly in a loop.
You should do something like this instead:
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
int main(int argc, const char * argv[]) {
int a[10] = {3, 0, 1, 4, 0, 0, 7, 20, 1, 5};
const int n = 10;
// counts the number of 0's in the original array
int zeroes = 0;
for (int i = 0; i < n; ++i)
{
if (a[i] == 0)
{
++zeroes;
}
}
// creates a new array and makes each element 0
// there's actually no need to allocate this dynamically at all...
int *array = calloc(1, sizeof(int[n]) );
assert(array != NULL);
// skip zeroes, ie "move the zeroes from the original array"
int* not_zeroes = array + zeroes; // point at first item to contain "not zeroes"
// adds the non-zero elements of the original array to the new array
for (int i = 0; i < n; ++i)
{
if(a[i] != 0)
{
*not_zeroes = a[i];
not_zeroes++;
}
}
// prints the array out in a nice format
printf("%s", "{");
for (int i = 0; i < n; ++i)
{
printf("%d,", array[i]);
}
printf("}\n");
free(array);
return 0;
}
This is my first time asking so please be gentle lol.
So I am trying to better understand arrays in C. Is there a way I can add an element to an array without using a for loop? The problem is I want to add a new element to the end of the array, but without knowing the size of the array.
So I already have this:
#include <stdlib.h> //not sure if needed but put it just in case
int main(void):
float real[20];
real[]={1,2,3,4,5};
I want to add the number 6 to the array, but I don't want to use real[5]=6. Is there another way to add an element to the end of the array without a loop checking if each element in the array until the element is null? Thanks for your help in advance!
C arrays don't know about their length. If you need arrays that can grow and shrink, you have to keep extra information on how long your active array is. An array that is created on the stack like so:
real array[20] = {1, 2, 3};
will contain twenty elements, the first three initialised with concrete values, the rest initialised to zero. If you want to consider this array as an array of initially three values that can hold up to 20 values, you have to keep the actual array length as an extra variable:
real array[20] = {1, 2, 3};
int narray = 3;
You can then append a value. Take care not to overflow that maximum storage of 20 elements:
if (narray < 20) array[narray++] = 9;
You can read the last value and remove it from the array:
if (narray) printf("%g\n", array[--narry]);
Here, you have to take care not to underflow the array. (Also, don't decrement narray more than once in the same expression, which will lead to undefined behaviour.)
If you write a function that operates on the array, pass both array and length:
void array_print(float array[], int n)
{
int i;
for (i = 0; i < n; i++) {
if (i) printf(", ");
printf("%g", array[i]);
}
printf("\n");
}
and call it like so:
array_print(array, narray);
Another approach is to keep a sentinel value like 0.0. This can be useful in some cases, but it has the disadvantage that you have to traverse the whole array to find out the length. It also removes the sentinel from the range of valid values that your array can hold.
The advantage here is, of course, that the array is "self-contained", i.e. you don't have to pass array and length to a function; just the array is enough. When appending you still have to take care not to overflow the maximum storage, which makes this approach cumbersome.
The only way is to keep a pointer to the next free position in the array. For example
#include <stdio.h>
float * copy( const float *src, size_t n, float *dst )
{
while ( n-- ) *dst++ = *src++;
return dst;
}
int main(void)
{
float real[20];
float *p = real;
p = copy( ( float [] ){ 1, 2, 3, 4, 5 }, 5, p );
p = copy( ( float [] ){ 6, 7 }, 2, p );
for ( float *q = real; q != p; ++q ) printf( "%1.1f ", *q );
printf( "\n" );
return 0;
}
The output is
1.0 2.0 3.0 4.0 5.0 6.0 7.0
You always can check whether p points within the array using condition
p < real + 20
The other approach is to use a structure that contains an array. For example
struct Array
{
enum { N = 20 };
float real[N];
size_t n; /* current number of filled elements */
};
With a little help of the preprocessor, you can use a compound literal to get the size:
int main(void)
{
#define REAL_VALUES 1, 2, 3, 4, 5
float real[20] = {REAL_VALUES};
real[sizeof((float[]){REAL_VALUES}) / sizeof(float)] = 6;
return 0;
}
In C you can get the length of an array with the expression sizeof (array) / sizeof (array)[0], or even better, by defining a macro:
#define LEN(array) \
((int) (sizeof (array) / sizeof (array)[0]))
What you describe is not adding an element to the end of the array but rather adding an element after the last element inserted. For that you need a variable that keeps track of the element count:
int count = 0;
float x;
...
if (count < LEN(real)) {
real[count] = x;
count++;
}
Observe, however, that once you have passed the array to a function its length is gone, so you need to pass the array length to the function as well:
void foo(float a[], int len);
...
foo(real, LEN(real));
You can use memset() to make space for your element in your array and then insert your element at specific position.
Here is sample code below.
/*Make space for number to insert.*/
memmove(&arr[pos+1],&arr[pos],(ARR_SIZE+1-pos)*sizeof(int));
arr[pos] = num;/*insert the number.*/
Full code snipet could be found here InsertElement
new here, trying to learn a piece of C with the great help of you guys, this could be a basic questions here....sorry you have start from basic.
void main()
{
char* arr[3] = {"baba","tata","kaka"};
char* arr1[3] = {"baba1","tata1","kaka1"};
char* arr2[3] = {"baba2","tata2","kaka2"};
char** array_all[] = {arr,arr1,arr2};
printf("%s\n",*array_all[0]);
//please guide me how to access individual entity(as arr[1], arr1[2],arr3[1]) //from each array using array_all
}
I'm not sure if this is exactly what you were looking for.. but this is what I understand so far.
You are wanting to access the individual elements of array_all (the elements arr, arr1 and arr2)? If so then all you do is...
array_all[0][i];
Where i is the element that you want to access.
The reason for this is because the index operators ([ and ]) actually dereferences a pointer and offsets the pointer (as in adds it by some integer, i.e. you move down in memory) that you specify. I recommend reading up on pointer arithmetic if you have no clue what happens if you add a pointer by some integer.
For example:
int x[] = { 1, 2, 3 };
// writing x[i] is the same as *(x + i)
int i = 2; // the element you wish to access
*(x + i) = 4; // set the ith (3rd) element to 4
*(x + 1) = 43; // set the 2nd element to 43
// Therefore...
// x now stores these elements:
// 1, 43, 4
// proof: print out all the elements in the array
for(int i = 0; i < 3; ++i)
{
printf("x[%i]=%i\n", i, x[i]);
}
Also, writing x[0] is the same as writing *x, since the array name actually points to the first element of the array.
OH and one thing, main should actually return an integer result. This is mainly used for error checking in your program, 0 usually means no error occurred and every other error-code (number other than 0) is some specific error related to your program, that you can choose.
i.e.
int main()
{
// e.g. for an error code
/*
if(someErrorOccured)
{
return SOME_ERROR_OCCURED_RETURN_VALUE;
}
*/
return 0; // this is at the end of the function, 0 means no error occured
}
change your printf statement line with this..
printf("%s\n",array_all[i][j]);
In place of i keep your array number and in place of k give your required element number. It works.