An array is preserving data between function calls in C - c

Why is the data preserved for the second call when I haven't used static?
Here is the code, the output and what I've expected the output should be.
#include <stdio.h>
void fun(int len)
{
int arr[10];
int i;
for (i = 0; i < len; i++)
arr[i] = (i+1) * 10;
for (i = 0; i < 10; i++)
printf("%d ", arr[i]);
printf("\n");
}
int main(void) {
fun(10);
fun(4);
return 0;
}
output:
10 20 30 40 50 60 70 80 90 100
10 20 30 40 50 60 70 80 90 100
expected output:
10 20 30 40 50 60 70 80 90 100
10 20 30 40 0 0 0 0 0 0

int arr[10]; declares an array of 10 int elements on the stack. Its elements are uninitialized. If you attempt to access them without initialization, as is the case with fun(4), you may see garbage values, you may happen to see old memory contents (as you did here), or you may crash the program with a segmentation fault if the memory page belongs to another program. You may even get your expected output! In fact, anything can happen because behavior is undefined by the specification.
To meet your expectations, initialize the array in any way you choose, such as one of the following:
int arr[10] = {};
int arr[10] = {0};
int arr[10];
memset(arr, 0, sizeof(int) * 10);
int arr[10];
for (int i = 0; i < 10; i++) {
arr[i] = 0;
}
etc.

Please initialize array.
Like this
void fun(int len)
{
int arr[10] = {0}; //changed
int i;
for (i = 0; i < len; i++)
arr[i] = (i+1) * 10;
for (i = 0; i < 10; i++)
printf("%d ", arr[i]);
printf("\n");
}

You are invoking undefined behavior by accessing uninitialized memory. The result could be literally anything, including your computer growing legs and running away.
In practice, what is probably happening is that your function calls occupy the same place on the stack since there are no other calls between or within them. The arr variable ends up on the same spot on the stack both times. The first initialization is more comprehensive than the second, so you don't see total garbage. This is to be expected, but certainly never relied upon.

array arr[] is allocated in stack which is uninitialized by default, the values are the ones used last time this area was allocated, in this it happens to allocate the same stack area between the 2 fun calls, and the stack area was initialized by the first call.

Related

Dynamic memory allocation with / without function

I tried creating function that dynamically allocates memory for 2 dimensional array and put some integer values into the array. Overall, the function worked as expected but there were some error. So I did the same thing within main() and got the right result. My code is like below:
#include <stdlib.h>
#include <stdio.h>
void test(int d1, int d2, int ***p){
int value;
*p = (int **)(malloc(sizeof(int)*d1));
for (int i = 0; i < d1; i++){
(*p)[i] = (int *)(malloc(sizeof(int)*d2));
for (int j = 0; j < d2; j++){
(*p)[i][j] = i * 10 + j;
}
}
printf("\n");
}
int main(void){
int d1, d2;
int ** ptr;
printf("length of 1st dimension?\n");
scanf("%d", &d1);
printf("length of 2nd dimension?\n");
scanf("%d", &d2);
test(d1, d2, &ptr);
for (int i=0; i<d1; i++){
for (int j=0; j<d2; j++){
printf("%d ", ptr[i][j]);
}
printf("\n");
}
free(ptr);
ptr = (int **)(malloc(sizeof(int)*d1));
for (int i=0; i< d1; i++){
ptr[i] = (int *)(malloc(sizeof(int)*d2));
for (int j=0; j<d2; j++){
ptr[i][j] = i *10 +j;
}
}
printf("\n######################\n\n");
for (int i=0;i<d1;i++){
for (int j=0; j<d2;j++){
printf("%d ", ptr[i][j]);
}
printf("\n");
}
free(ptr);
return 0;
}`
When I passed 5 as a length of 1st and 2nd dimension, I got the result like below:
length of 1st dimension?
5
length of 2nd dimension?
5
532699424 32725 2 3 4
10 11 12 13 14
20 21 22 23 24
30 31 32 33 34
40 41 42 43 44
######################
0 1 2 3 4
10 11 12 13 14
20 21 22 23 24
30 31 32 33 34
40 41 42 43 44
I think, except that I passed pointer to pointer to pointer as an argument to the function, I did the same thing. However some values in the first row are different. And I got different value for the first row whenever I executed the function.
Could someone please let me know what I did wrong?
Thank you in advance.
The lines
*p = (int **)(malloc(sizeof(int)*d1));
ptr = (int **)(malloc(sizeof(int)*d1));
are wrong. The elements is int*, but only room for int is allocated per element.
This may cause trouble if int* is larger than int (for example, when int* is 8 bytes and int is 4 bytes).
The lines should be
*p = malloc(sizeof(int*)*d1);
ptr = malloc(sizeof(int*)*d1);
or (with risk of making mistake reduced by avoiding writing type manually)
*p = malloc(sizeof(*p)*d1);
ptr = malloc(sizeof(*ptr)*d1);
See also: c - Do I cast the result of malloc? - Stack Overflow

Sort working in main() but not in separate function

I'm working on a homework problem for C and unix programming, and the teacher told us to write a sort function for an array in C.
I've got sorting working from some for loops in main, but the separate sort function we need doesn't work.
#include <stdio.h>
#include <stdlib.h>
int Sort(int arr[], int size){
int i,j,a;
for(i = 0; i < size; i++){
for(j = i+1; j < size; j++){
if(arr[i] > arr[j]){
a = arr[i];
arr[i] = arr[j];
arr[j] = a;
}
}
return arr;
}
}
int main(){
int a;
int BAT[40];
for(int i=0; i < 40; i++){
BAT[i] = (float)(599)* ( (float)rand() / (float)RAND_MAX );
printf("%d \n", BAT[i]);
}
printf(" the array should now be sorted \n");
//Sort(BAT, 40); THIS IS THE FUNCTION CALL THAT DIDNT SEEM TO WORK SO I COPIED THE SORT OUT OF THE SORT FUNCTION TO TEST
//THIS IS THE SORT CODE AND WHILE IT IS IN THE MAIN IT WORKS
for(int i = 0; i < 40; i++){
for(int j = i+1; j < 40; j++){
if(BAT[i] > BAT[j]){
a = BAT[i];
BAT[i] = BAT[j];
BAT[j] = a;
}
}
}
//END OF SORTING TEST
for(int j=0; j < 40; j++){
printf("%d \n", BAT[j]);
}
I expect the Sort(BAT, 40) to sort the array which I then try to print but instead nothing seems to occur.
Your sort routine should have worked as written, but you are failing to enable warnings in your code and thus you are not allowing the compiler to help you fix the warnings and errors in your code -- that alone would have allowed your code to run just fine.
For instance, your compiler will tell you the exact line number, and many times the exact character in that line where the error or warning was detected, e.g.
bubblesortfn.c: In function ‘Sort’:
bubblesortfn.c:21:5: warning: return makes integer from pointer without a cast
[enabled by default]
return arr;
^
How can a return make an integer from a pointer?? Simple, you have your function attempting to return an integer array (int *), and you have your function declared int Sort. (you don't need to return anything, but you can simply fix it by changing your declaration to int *Sort (....)).
The remainder of the problems are simple syntax issues and unused variables (e.g. a in main()) that would be instantly flagged by your compiler -- listen to it. Let it help you write better code.
Always compile with warnings enabled, and do not accept code until it compiles cleanly without warning. To enable warnings add -Wall -Wextra -pedantic to your gcc/clang compile string. For clang, instead you can use -Weverything. For VS (cl.exe on windows), use /W3 (or use /Wall but you will get quite a few extraneous non-code related warnings). Read and understand each warning -- then go fix it.
As mentioned in my comment, don't use magic numbers in your code (except where absolutely required like with the fscanf field-width modifier). Instead, If you need a constant, #define one (or more), or use a global enum to do the same thing. That way you have one single place at the top of your code to change things if needed and you don't have to go picking through your declarations or loop limits to change things.
Literally, fixing the warnings identified and tidying things up a bit was all that was needed to get your code working and properly sorting the array in your Sort function (I also added a prnintarray() function to print your array to avoid the repeated loops in main(). Putting it altogether, and seeding the random number generator by calling srand() before you use rand(), you could do:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* if you need a constant, define one (or more) - avoid magic numbers */
#define ROWSZ 10 /* max integers to print per-row */
#define MAXB 40 /* max integers in BAT */
#define MULTP 599 /* multiplier constant */
int *Sort (int arr[], int size)
{
int i, j, a;
for (i = 0; i < size; i++) {
for (j = i + 1; j < size; j++) {
if (arr[i] > arr[j]){
a = arr[i];
arr[i] = arr[j];
arr[j] = a;
}
}
}
return arr;
}
/* simple print function to output arr of sz with rowsz int per-row */
void prnintarray (int *arr, size_t sz, size_t rowsz)
{
for (size_t i = 0; i < sz; i++) {
if (i && i % rowsz == 0)
putchar ('\n');
printf (" %4d", arr[i]);
}
putchar ('\n');
}
int main (void) {
int BAT[MAXB] = {0}; /* initialize all arrays - good practice */
srand (time(NULL)); /* seed the random number generator */
for (int i = 0; i < MAXB; i++) /* fill array */
BAT[i] = MULTP * ( (float)rand() / (float)RAND_MAX );
puts ("\nunsorted array:\n");
prnintarray (BAT, MAXB, ROWSZ);
Sort (BAT, MAXB);
puts ("\nsorted array:\n");
prnintarray (BAT, MAXB, ROWSZ);
}
Example Use/OUtput
$ ./bin/bubblesortfn
unsorted array:
461 519 346 508 265 93 358 407 278 151
465 531 430 148 181 227 452 206 401 202
103 518 259 267 342 495 570 431 477 455
164 339 375 511 248 42 6 8 450 284
sorted array:
6 8 42 93 103 148 151 164 181 202
206 227 248 259 265 267 278 284 339 342
346 358 375 401 407 430 431 450 452 455
461 465 477 495 508 511 518 519 531 570
Look things over and let me know if you have further questions.
Use qsort For Real-World Sorting
While there is nothing wrong with writing a bubblesort function for the learning aspect of it, the C-library provides qsort which can, and should, cover the majority of your sorting needs. Your only job in using qsort is to write a simple compare() function to tell qsort how to sort adjacent members of the array. The prototype for the compare() function usually sends new C programmers into a state of panic. The prototype is:
int compare (const void *a, const void *b)
Don't let it bother you. a and b are just pointers to the two members of your array currently being compared. Your job is to write the remainder of the function so that if the value pointed to by a:
sorts before the value pointed to by b, a negative number is returned;
is equal to the value pointed to by b, zero is returned and finally
sorts after b a positive values is returned. (all just like strcmp).
To handle the fact that a and b are void pointers, you simply cast them to int pointers before dereferencing to make use of their values, e.g.
int compare (const void *a, const void *b)
{
const int *pa = a, /* a and b are pointers to elements being compared*/
*pb = b; /* in array, cast as required to proper type */
Since your array is int, a and b will be pointers-to int, you simply cast them to int *. Now you can access the values through the pointers (e.g. dereference *pa to get the value at the address held by pa).
Now to satisfy the return requirements the trivial solution would be:
return *pa - *pb;
However, if the *pa is a large negative value and *pb is a large positive value, subtracting *pa - *pb can easily result in integer overflow and undefined behavior. Instead of a direct subtraction, by using two inequalities, chance of overflow can be eliminated while providing the needed return. Think through:
return (*pa > *pb) - (*pa < *pb);
So putting your qsort function together and replacing your call to Sort with a call to qsort, you would rewrite your code as:
int compare (const void *a, const void *b)
{
const int *pa = a, /* a and b are pointers to elements being compared */
*pb = b; /* in array, cast as required to proper type */
/* inequality avoids overflow from subtracting 2 large values
* (x > y) - (x < y) , returns -1, 0, 1 (like strcmp) for
* -1 -> x sorts before y, 0 -> x equals y, 1 -> x sorts after y
*/
return (*pa > *pb) - (*pa < *pb);
}
Then
qsort (BAT, MAXB, sizeof *BAT, compare);
Give it a try. As a bonus for large arrays, qsort will be Orders of Magnitude faster than a bubblesort (one of the slowest sorts for large arrays)

C - How would I extract Even numbers from an array and place them into another array called EvenNumbers?

I'm tasked with writing a function that will identify all the even numbers in an sample array {10,2,9,3,1,98,8] and place them in an array called EvenNumbers. I have to allow the function so that it works with different combinations of numbers in the array not just the numbers in the sample array above.
I'm wondering is there any way to add numbers to an array that could be different every time? How would I extract the even numbers an place them into an array? Also
for the even array size its giving me an error that the expression must have a constant value but when I use const int it still gives me that error.
Here is the full question.
"Using the array of sample values {10,2,9,3,1,98,8}, write a function that will identify all the even numbers in an array and place it in an array called EvenNumbers. The function must work in all cases, not just in the case of the array shown. Assume that the array size is always available through a global constant called MAX"
Here is what I have so far. I've no idea how I will extract the even numbers from a for loop and place them in an array. I also dont know what the "expression must have a constant value" is about?
#include <stdio.h>
#include <stdlib.h>
void EvenNumber(int Array[], int size);
int main()
{
int array[7] = { 10,2,9,3,1,98,8 };
EvenNumber(array, 7);
}
void EvenNumber(int Array[], int size)
{
int i;
int EvenArraySize;
for (i = 0; i < size; i++)
{
if (Array[i] % 2 == 0)
{
EvenArraySize++;
}
}
int Even[EvenArraySize];
}
The right way to go is to use malloc to allocate just the right amount of memory.
Count the number of even numbers
Allocate the space needed to store them
Copy even numbers in this space
Do whatever you want with these numbers
Free the allocated space
Snippet:
#include <stdio.h>
#include <stdlib.h>
#define MAX 7
int
main()
{
int array[] = {10,2,9,3,1,98,8};
int *even_numbers;
int i, nb_even_numbers;
for (i = 0, nb_even_numbers = 0; i < MAX; i++)
{
if (array[i] % 2 == 0)
nb_even_numbers++;
}
even_numbers = malloc(sizeof(int) * nb_even_numbers);
if (!even_numbers)
{
perror("malloc");
return 1;
}
for (i = 0, nb_even_numbers = 0; i < MAX; i++)
{
if (array[i] % 2 == 0)
even_numbers[nb_even_numbers++] = array[i];
}
/* do your stuff here */
free(even_numbers);
return 0;
}
First, you can never return a statically declared array from a function (even though you don't explicitly try, your Even array is destroyed when EvenNumber returns) Why? The function stack frame for EvenNumber is released for reuse on return and any locally declared arrays are no longer valid.
You either need to pass a second array as a parameter to EvenNumber, or you can dynamically allocate storage for Even in EvenNumber (with, e.g. malloc or calloc or realloc) and return a pointer to the beginning of the array. (you must also have some way to return the size or use a constant for a max size).
There is no need to use % (modulo) to test whether a number is odd/even. All you need to do is look at bit-0 (little endian). If it is 0, then the number is odd, if it is 1, then its even. Much more efficient than calling modulo which incorporates division.
Finally, main is type int and therefore returns a value.
Putting those pieces together, you can do something simple like the following:
#include <stdio.h>
#include <stdlib.h>
void EvenNumber (int *array, int *even, int size, int *esize);
int main (void)
{
int array[] = { 10,2,9,3,1,98,8 },
i, n = sizeof array / sizeof *array,
even[n], /* a VLA of the same size as array is fine here */
esize = 0;
EvenNumber (array, even, n, &esize);
printf ("array: ");
for (i = 0; i < n; i++)
printf (" %2d", array[i]);
printf ("\neven : ");
for (i = 0; i < esize; i++)
printf (" %2d", even[i]);
putchar ('\n');
return 0;
}
void EvenNumber (int *array, int *even, int size, int *esize)
{
int i;
for (i = 0; i < size; i++)
if ((array[i] & 1) == 0) /* simply looking at bit-0 is all you need */
even[(*esize)++] = array[i];
}
Note: esize is passed as a pointer to EvenNumber and updated within the function so that the number of elements in even are available back in the calling function (main() here).
Example Use/Output
$ ./bin/arrayeven
array: 10 2 9 3 1 98 8
even : 10 2 98 8
Let me know if you have any further questions.

Getting segmentation fault while printing output

I am trying to know how the array in c is working. so i was implementing some basic array concepts. when i run the program i got the exact output but at the end of the output it says segmentation fault.
int main(void)
{
int a[] = {};
printf("Enter the number:");
int n = get_int();
int m = 0;
for(int i = 0; i<n; i++)
{
printf("insert:");
m = get_int();
a[i] = m;
}
for(int j = 0; j < n; j++)
{
printf("%d\n", a[j]);
}
}
output:
Enter the number:3
insert:1
insert:2
insert:3
1
2
3
~/workspace/ $ ./arr_test
Enter the number:5
insert:1
insert:2
insert:3
insert:4
insert:5
1
2
3
4
5
Segmentation fault
see for the first output it has a size of 3 it doesn't show segmentation fault but for second one it has a size of 5 it shows. so why its happening and what mistake i made.
You need to allocate memory for the array. Something like:
int main(void) {
int *a;
...
int n = get_int();
...
a = malloc(n * sizeof(int));
if (!a) {
// Add error handling here
}
...
}
If you know the size of the array you want to make ahead of time, declare it like int a[128]; instead of just int a[]; so a at indices 0 to 127 will be safe to write to (and subsequently read from).
If you want to declare an array of size n at runtime, use int a[] = malloc(n * sizeof(int)); or int *a = malloc(n * sizeof(int));. Make sure a is not NULL before using it, and remember to call free(a); when you are done with it to avoid a memory leak.

C: Return even number in array program by using pointers, why does my program crush after printing the result

This is my simple program that generate a array of N integers, print it, and it will call the getevennumber function, and the function will return the pointer addresses of the even numbers in array. and the main program will print the even numbers in the array:
#include <stdio.h>
int* getEvenNumber(int a[]);
int main (){
int N;
printf("Enter N: ");
scanf("%d", &N);
int array[N], i;
int *test[N];
srand(time(NULL));
for(i = 0; i < N; i++)
{
array[i] = (rand() % 100)+1;
printf("%d \n", array[i]);
}
printf("------- \n");
*test = getEvenNumber(array);
for(i = 0; i <= sizeof(test); i++){
printf("%d \n", *test[i] );
}
return 0;
}
int* getEvenNumber(int a[]){
int i,j = 0;
int* ptr[j];
for(i = 0; i <= sizeof(a); i++)
{
if (a[i] % 2 == 0)
{
ptr[j] = &a[i];
printf("%d\n",*ptr[j]);
j++;
}
}
return *ptr;
}
currently the problem is: when I run the program, it will print the desired even numbers, then the program will also print 2 random data address then crushes, here is an example output:
N: 10
66
19
70
54
84
12
35
56
53
19
66
70
54
84
19
1981890690
-1090571325
(program crushed)
Can someone help me identify the problem please, thank you!
In the function getEvenNumber, you're creating a local variable ptr which adress you are returning. You should not do that, because local variables only exist within a function, and never outside of it. Also, you are actually returning the value of the first element of ptr (because you are dereferencing it). This is why *test[i] fails, because you never return the actual array and thus cannot iterate over it with [i].
The best solution would be to declare the array in the main function and pass it like this getEvenNumber(int a[], int *ptr[])
And don't declare your array with size zero... (as you are currently doing with ptr).
for(i = 0; i <= sizeof(test); i++){
printf("%d \n", *test[i] );
}
sizeof(test) isn't the number of elements in the array test, it's sizeof(int*) which is 8 (bytes), assuming you're on a 64-bit system. It's returning the size of a pointer to a memory address, not the actual length of the array. So your loop goes outside the bounds of the array which probably causes your problem.
Also you're returning a local variable, which can cause additional problems.

Resources