Array made with malloc function goes beyond desired size [duplicate] - c

This question already has an answer here:
Why the size of pointer to array is always 8 in C? [duplicate]
(1 answer)
Closed 3 years ago.
I'm making a program capable to use some statistics functions. For that, I used malloc for the array that the numbers of the sample to operate on, as I want it's size to be based on users' input. It's not the first time I do this, and it worked fine, but this time I can't set the size as needed and I can't find the flaw.
Below is the necessary code for the creation and printing of the array, skipping main() as it only runs the functions.
int *sample;
int MakeSample()
{
int sampleSize;
int valueN;
printf("Enter size of your sample: ");
scanf("%d", &sampleSize);
sample = malloc(sampleSize * sizeof(int));
for (int i = 1; i <= sampleSize; i++)
{
printf("Enter value #%d: ", i);
scanf("%d", &valueN);
sample[i - 1] = valueN;
}
}
int PrintSample()
{
for (int k = 1; k <= sizeof(sample); k++)
{
printf("Value #%d: %d\n", k, sample[k - 1]);
}
}
If I enter size 1 for the array, that should be the amount off values asked for and printed, instead I got this:
Value #1: 1
Value #2: 0
Value #3: 0
Value #4: 0
Value #5: 0
Value #6: 0
Value #7: 133057
Value #8: 0

sample is an int pointer; sizeof(sample) is always 8. You need to store the sampleSize variable somewhere and use that instead - there's no way for your program to know how big your array is otherwise, since it's not really an "array", it's a pointer to memory that happens to hold an array.

Related

Declaring Array in C with variable length [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
This block of code gives me the fibonacci numbers
#include <stdio.h>
int main()
{
int n; //integer overflow error for n > 47
printf("How many Fibonacci numbers?\n");
scanf("%d", &n);
int fibs[n];
fibs[0] = 0;
fibs[1] = 1;
printf("%d ", fibs[0]);
printf("%d ", fibs[1]);
for(int i = 2; i < n; i++)
{
fibs[i] = fibs[i - 2] + fibs[i - 1];
printf("%d ", fibs[i]);
}
return 0;
//gives 0 1 1 2 3 5 8 13 21 34 for n = 10
}
But this gives me the wrong output but no errors
#include <stdio.h>
int main()
{
int n, fibs[n];//change
printf("How many Fibonacci numbers?\n");
scanf("%d", &n);
fibs[0] = 0;
fibs[1] = 1;
printf("%d ", fibs[0]);
printf("%d ", fibs[1]);
for(int i = 2; i < n; i++)
{
fibs[i] = fibs[i - 2] + fibs[i - 1];
printf("%d ", fibs[i]);
}
return 0;
//gives 0 1 for n = 10
}
I know it definitely has something to do with the array and its size not being defined but I'm having trouble understanding what exactly is the problem.
Could someone explain what is going on here?
int n, fibs[n]; attempts to define an array using n for the length, but n has not been initialized, so its value is not determined. Common consequences include:
The definition behaves as if n has some small value, possibly zero, and then the following code attempts to store values in the array but overruns the memory reserved for it and thus destroys other data needed by the program.
The definition behaves as if n has some large value, causing the stack to overflow and the program to be terminated.
For example, storing 0 to to fibs[0] or 1 to fibs[1] might write to the memory reserved for n. Then the for loop terminates without executing any iterations because the test i < n is false.
The one big thing that I see in your code is the line int n, fibs[n];. The variable n is located on the stack since it's a local variable. That means that it's value can literally be anything before it's initialized. And since you are declaring an array using that value, the array has a random, unknown length. If it works, then that is purely coincidence. This is why your first code version works because the array is declared AFTER the scanf which initializes n. I think a better way of creating an array with a variable number of array elements is to use malloc instead...
int n, *fibs;
printf("How many Fibinocci numbers?\n");
scanf("%d", &n);
fibs = malloc(sizeof(int) * n);
if (fibs == NULL)
{
fprintf(stderr, "Unable to allocate sufficient memory for operation.\n");
exit(1);
}
Then you can use array indices fibs[0], fibs[1], etc... to access different locations in the block of memory.
Why does this work? Because int fibs[n] is LIKE a pointer to a block of memory. Technically, they are not the same, but you can generally use a pointer to a block of memory as an array. This will only work with single dimensional arrays because the compiler has no idea how many columns there are. But to work around that, you can compute that manually like this (i is the row, j is the column):
array[i * columns + j];

Array size mismatch - C [duplicate]

This question already has answers here:
How do I determine the size of my array in C?
(24 answers)
random number in while loop [C programming] [duplicate]
(2 answers)
How can one print a size_t variable portably using the printf family?
(14 answers)
Closed 2 years ago.
I'm writing a program in C to add random numbers to an array. The size of the array is given (say n = 250) and using rand(), I'm generating these numbers (range is 1 to 100).
int main()
{
int n = 250;
int array[n];
for (int i = 0; i < n; i++)
{
srand(time(NULL));
int r = rand()%100 + 1;
array[i] = r;
}
printf("Output Size: %lu\n", sizeof(array));
return 0;
}
When I run the code, the result is-
Output Size: 1000
Expected result is 250. What am I doing wrong?
I think you're expecting n as output (number of elements in the array); but you're doing it wrong. Currently, what you're getting is 250*4 = 1000 (i.e., size of int is 4, and the number of elements is 250).
Replace sizeof(array) with sizeof(array)/sizeof (array[0])
Read this to dive deeper.
sizeof(type) returns the size, in bytes, of the type.
To find out size of array, you can do:
printf("Output Size: %zu\n", sizeof(array)/sizeof(array[0]);
Also, the type of the result of sizeof operator is size_t. You should use %zu format specifier instead of %lu.
You have 250 elements array, each array element is of size 4 bytes.
250*4 = 1000.
And you don't need to call srand in loop.
read this article about srand.

For loop assignments overflow into another variable [duplicate]

This question already has answers here:
How do I determine the size of my array in C?
(24 answers)
Closed 8 years ago.
I am trying to use a for loop to assign values to an array in C (I'm using minGW). At first I tried doing:
double flag[5] = {0.1};
but that only assigned the first variable in the array to 0.1. Then I tried doing a for loop to assign each individually. The reason why I don't want to hard code it is because I want the size of the flag variable to be flexible to the user's input. My current code looks like this:
int cnt;
double flag[5];
for (cnt = 0; cnt < sizeof(flag); cnt++) {
printf("sizeof(flag) is %d\n",sizeof(flag));
printf("size is equal to %d and cnt is %d\n",size,cnt);
flag[cnt] = 0.1;
}
printf("size is equal to %d\n",size);
The variable "size" changes from 6 as it was previously determined to a garbage number, and I cannot modify the number of iterations. For example, if I set cnt < sizeof(flag)-1, there is no change. -2,-5, etc no change. However if I drastically reduce the size, it gets stuck in an infinite loop. sizeof(flag) is 40, not 5 like I'd want it to be, but dividing by 8 also gets it into an infinite loop somehow. Any advice?
This question was answered, thank you everyone!
The number of elements of flag array is not:
sizeof (flag)
but
sizeof flag / sizeof *flag
The former is the size in bytes of the array, the latter is the size in bytes of the array divided by the size in bytes of one element of the array.
change :
for (cnt = 0; cnt < sizeof(flag); cnt++)
to
for (cnt = 0; cnt < sizeof(flag)/sizeof(double); cnt++)
use
for (cnt = 0; cnt < sizeof flag / sizeof *flag; cnt++)
{
}
sizeof() returns # of bytes required for that variable which is 5*sizeof(double). So your loop is running for more than 5 times causing overflow.
Apart from the solutions suggested in earlier answers, you can have a macro for size of the array and use this macro and run loop till that value.
#define SIZE 5
.
.
.
int cnt;
double flag[SIZE];
for (cnt = 0; cnt < SIZE; cnt++) {
printf("sizeof(flag) is %d\n",sizeof(flag));
printf("size is equal to %d and cnt is %d\n",size,cnt);
flag[cnt] = 0.1;
}
printf("size is equal to %d\n",size);

How to correctly compare and print out matching elements in this array in C?

I have this simple problem to which I am trying to write a solution, in C.
If an array arr contains n elements, then write a program to check
if arr[0] = arr[n-1], arr[1] = arr[n-2] and so on.
And my code looks like this-
#include<stdio.h>
int main()
{
int arr[10],i=0,j;
int k=0;
printf("\n Enter 10 positive integers: \n");
for(k=0;k<=9;k++)
scanf("%d",&arr[k]);
while(i<=9)
{
for(j=9;j>=0;j--)
{
if(arr[i]==arr[j])
{
printf("\n The array element %d is equal to array element %d\n", arr[i],arr[j]);
}
i++;
continue;
}
}
return 0;
}
On entering this input-
Enter 10 positive integers:
10
20
30
40
50
60
40
80
20
90
The output I get is-
The array element 20 is equal to array element 20
The array element 40 is equal to array element 40
The array element 40 is equal to array element 40
The array element 20 is equal to array element 20
Now, there are two problems with this code-
As you can see, the program prints out matching array elements twice. This is because, the way I've structured the program, once the variable i loops through the array from the first to last element, and then j loops through from the last to first element. So each prints out the matching array element once, leading to two sets of values.
My second question is- In my code, I've hard-coded the length of the array in the for loops(0 to 9 for an array of 10 elements). What change can be done so that the length of the array, as entered by the user, can directly be used in the for loops?
I've read that, in C, array dimensions(when declaring) cannot be a variable. So, a declaration like this(which was my first thought) wouldn't work-
int n; // n is no. of elements entered by the user
int arr[n];
I'm a newbie to programming, so my apologies if the question sounds/is too simple, low-quality.
Thank You.
1)You can traverse the array for half times for getting the prints only once. Instead of for(j=9;j>=0;j--) you can use for(j=9;j>=9/2;j--).
2)
int n;
int arr[n].
Recent Compilers support this statement. If you don't like to use this, you can go for dynamic memory allocation for the array.
My second question is- In my code, I've hard-coded the length of the array in the for loops(0 to 9 for an array of 10 elements). What change can be done so that the length of the array, as entered by the user, can directly be used in the for loops?
Use dynamic memory allocation. Use malloc().
So code will be
{
int num_elements;
int* arr;
printf("Enter number of elements\n");
scanf("%d", &num_elements);
arr = (int *) malloc(num_elements * sizeof(int)); // Use this 'arr' for holding input data from user
// Your remaining code comes here
free(arr); // Free the pointer in the end of program
}
the variable length creation works for me:
#include<stdio.h>
int main(){
int a, i;
scanf("%i", &a);
int blah[a];
for (i = 0; i < a; i++){
printf("/n%i", blah[a]);
}
}
The other way would be to create the maximum length array and than simply use first n elements.
As the previous answer states it is up to you to make sure you are checking each element only once therefore stopping at the element n/2. It is probably important that n/2 is rounded to the closest smaller integer, so at first glance odd numbers of arguments may be differently handled. But as it is omitting only the middle element it is identical to itself.
For your first query
for(i=0;i<n/2;i++)
{
if(a[i]==a[n-(i+1)])
{
printf("\n The array element %d is equal to array element %d\n",a[i],a[n-(i+1)]);
}
}
For your second query you can use condition i<(n/2) (which runs the loop (n/2)-1 times) For your case where n = 10 it will run from 0 to 4.
If you want to loop from 0 to 9 you can use
for(i=0;i<n;i++)
For making array of n elements where n is a variable either make an array of elements that is always greater than n or do it by making a dynamic array.
http://www.cs.swarthmore.edu/~newhall/unixhelp/C_arrays.html
corrected:
#include<stdio.h>
int main()
{
int i=0, size; // size of array
int k=0; // counter
printf("enter size of array\n");
scanf("%d", &size); // ask user for desired size
int *arr = malloc(size * sizeof(int)); // allocate memory for array
printf("\n Enter 10 positive integers: \n"); // fill your array of size size
for(k=0;k<size;k++)
scanf("%d",&arr[k]);
k = 0; // reset this counter
for(i=0; i<size/2; i++) // check only for half of it
{
if(arr[i] == arr[size-i-1]) // try it with paper and pincil
{
printf("match arr[%d]=arr[%d]=%d\n", i,size-i-1, arr[i]);
k++;
}
}
if(k==0) printf("No matching");
return 0;
}

How could it be possible to read and write past the array

Output of the program:
#include <stdio.h>
int main()
{
int size;
printf("Enter the size of array: ");
scanf("%d",&size);
int b[size],i = 0;
printf("Enter %d integers to be printed: ",size);
while(i++ < size)
{
scanf("%d",&b[i]);
printf("%d %d\n", i, b[i]);
}
return 0;
}
for size = 5 and input numbers :
0 1 2 3 4
is
1 0
2 1
3 2
4 3
5 4
where first column is for i and second for elements of array b.
It is clear that i in the loop while(i++ < size) { incremented to 1 before entering the loop. This loop should have to store/print the value at/of b[1], b[2], b[3], b[4] but not b[5] as loop will terminate at i = 5.
How this code is printing the value of b[5]?
I have tested it for different array size and it is not printing any garbage value.
By reading and writing past the array, your program invokes undefined behavior. It doesn't mean that it has to crash or print garbage values, it can pretend working fine. Apparently, that's what is happening in this case.
In your loop, the condition i < size is checked before i is incremented. But, i is incremented before entering the body of the loop and not after it, so it is possible to access b[5] in this case, as i would be incremented after checking i < size with i=4. You do not want that, as this causes undefined program behavior.
If you try to access an element in the array which does not exist, e.g. array[size], you are accessing the next spot in the memory right after the array. In this case you are lucky, but if this meant you were accessing a part of the memory where your program isn't allowed to do so, you'd get a segmentation fault.
you could use a for cycle instead of a while so instead of while(i++<size)you could use for(i = 0; i < size; i++) that should solve your problem my friend :)

Resources