How to use variable length array in gcc? - c

So, I've read on this site that c++ doesn't allow variable length array but gcc allows it. So, I wanted to test a small code
#include<stdio.h>
#include<stdint.h>
void main()
{
int8_t n;
int8_t var_array[n];
int8_t i;
printf("Enter array size: \r\n");
scanf("%d", &n);
for(i=0; i<n; i++)
var_array[i] = i;
for(i=0; i<n; i++)
printf("var_array[%d] = %d\r\n", i, var_array[i]);
}
The code compiles with "gcc var_array.c -o var_array" command in linux OS but when I run it, I get segmentation fault error
Enter array size:
5
Segmentation fault
What am I doing wrong?

Also make it int, as you are using %d specifier. (because earlier will only be of 8 bits which might overflow in case of large values)
int n;
int i;
printf("Enter array size: \r\n");
if( scanf("%d", &n) != 1 ){
fprintf(stderr,"%s\n","Error in input");
exit(1);
}
int var_array[n];
for(i=0; i<n; i++)
var_array[i] = i;
...
You were using an unintialized variable. And then based on new valu eof n accessing the array. The indices most probably indexed out of the bound of the array giving you seg fault.
For inputting int8_t use scanf("%" SCNd8, &n);. You can also input the int8_t type.
Yes scanf's return value must be checked.
So the ideal call would be
if( scanf("%d",&n) == 1 ){
//...success..do work
}

The Mistake in the program is
int8_t n; //Here n is declared where n has random value
int8_t var_array[n]; /*Now in this statement you have declared array
with the size of that random value*/
So You get that error,In order to rectify that you have to get the input value of n and then you declare the var_array[n]

Related

Segmentation fault in c dealing with scanf

I'm writing a program that requires me to do a union of two arrays. Here is my code so far.
I get Segmentation fault as an error after I enter set A.
#include <stdio.h>
void Union(int a[], int b[], int set1, int set2)
{
int u[20], i, j, unionIndex=0,trigger;
for(i=0; i<set1; i++)
{
u[unionIndex] = a[i];
unionIndex++;
}
for(i=0; i<set2; i++)
{
trigger=0;
for(j =0; j<set1; j++)
{
if(b[i] == u[j])
{
trigger =1;
break;
}
}
if(trigger =0)
{
u[unionIndex]=b[i];
unionIndex++;
}
}
for(i=0;i<unionIndex;unionIndex++)
{
printf(" %d",u[i]);
}
}
int main(void) {
int N=0;
int M=0;
int i;
int j;
printf("Please enter the number of elements in set A: ");
scanf("%d",N );
int a[N];
printf("Enter the numbers in set: ");
for(i=0;i<N;i++)
{
scanf("%d",&a[i]);
}
printf("Please enter the number of elements in set B: ");
scanf("%d",M );
int b[M];
printf("Enter the numbers in set: ");
for(j=0;i<M;i++)
{
scanf("%d",&b[i]);
}
Union(a,b,N,M);
return 0;
}
I'm pretty sure the issue has something to do with arrays because the program will compile but i get the error right after the user enters set A. I'm a beginner at C but I know a lot more about Java, so I'm thinking this has something to do with memory allocation. I'm not really sure how to solve the issue, so if you could point me in the right direction that would be helpful.
You need to pass the address of the variable to scanf()
Change
printf("Please enter the number of elements in set A: ");
scanf("%d",N );
to
printf("Please enter the number of elements in set A: ");
scanf("%d", &N);
Same goes for other place
printf("Please enter the number of elements in set B: ");
scanf("%d", &M);
There is another possible mistake
Its here
for(j =0; j<set1; j++)
{
if(b[i] == u[j])
In this set1 is equal to N, so j will go from 0 to N-1. And array u[] has only 20 elements. There is a possibility of array access out of bound if some user enter value more then 20 for N.
The problem, as I see it is in
scanf("%d",N );
and
scanf("%d",M );
It invokes undefined behavior as scanf() needs the argument to a format specifier to be a pointer to the type.
Just to clarify, you're essentially passing the address as 0 (value of the variable), which is not a valid addres, anyway.
You need to pass the address there, like
scanf("%d", &N );
and
scanf("%d", &M );
That said, in your Union() function, you're using a user-defined value to limit the for loop, against a constant value 20. In case the user input is more than 20, you'll be overrunning the memory which invokes undefined behavior.
The reason you're getting the segmentation fault is because of how you're calling scanf when reading in N and M. The %d format specifier for scanf expects an int *, i.e. the address of an int, but you're passing in an int. This is undefined behavior.
So you can fix them like this:
scanf("%d",&N );
....
scanf("%d",&M );
Some addtional bugs:
When looping to read in the values for b:
for(j=0;i<M;i++)
{
scanf("%d",&b[i]);
}
You have the wrong loop indexes:
for(j=0;j<M;j++)
{
scanf("%d",&b[j]);
}
When checking trigger:
if(trigger =0)
This is an assignment, not a comparison:
if(trigger == 0)
When looping to print out u:
for(i=0;i<unionIndex;unionIndex++)
You're incrementing the wrong variable:
for(i=0;i<unionIndex;i++)
Finally, u need to have a length of at least set1 + set2, otherwise you risk writing off the end of the array:
int u[set1+set2];
Fix those and you should get the desired results.

My program crashes, I don't understand why it does not even reach the first printf

My program is supposed to order a list of numbers inputed by the user, but it crashes even before reaching the first printf. My compiler makes 2 warnings, but I don't see the issue. I haven't studied pointers yet, so I didn't want to use them. Here are the messages:
In function `selection_sort':
[Warning] passing arg 2 of `selection_sort' makes pointer from integer without a cast
In function `main':
[Warning] passing arg 2 of `selection_sort' makes pointer from integer without a cast
.
#include<stdio.h>
int selection_sort(int n, int v[n])
{
int high = v[0];
int i;
for(i = 0; i < n; i++)
high = high < v[i]? v[i] : high;
if(n - 1 == 0)
return;
v[n - 1] = high;
n -= 1;
selection_sort(n, v[n]);
}
int main(void)
{
int n, i;
int v[n];
printf("Enter how many numbers are to be sorted: ");
scanf("%d", &n);
printf("Enter numbers to be sorted: ");
for(i = 0; i < n; i++)
scanf("%d", &v[i]);
selection_sort(n, v[n]);
printf("In crescent order: ");
for(i = 0; i < n; i++)
printf("%d ", v[i]);
getch();
return 0;
}
Your program is using a variable length array, a feature that was added in C99.
However, you declare its size based on an uninitialized variable. What did you believe would happen there?
In C, variables declared inside functions are NOT set to 0. They are not set to anything. They pick up whatever value was left on the stack or in the register that they are assigned.
I believe that your program is crashing because n in int v[n] is a ridiculously big number and v is trying to use too much memory.
You can probably fix this by moving your array declaration below the scanf that reads in n.
You need to pass v, not v[n] to the function selection_sort. v is the array, v[n] is actually an out of bounds element of v.
the line should be selection_sort(n, v);

Unwanted Output in C Program

I have a class project to make an array, declare it's size (add 1) then fill it in numerical, nondecreasing order. After that, I need to declare x, a value to be added to the array in the appropriate spot, so the array is still nondecreasing.
The program builds without error (for once!) but I'm getting some really weird outputs.
#include <stdio.h>
int main (void) {
//Local Declarations
int size;
int ary[100];
int x;
int i;
int j;
//Statements
printf("Enter the size of the array: ");
scanf("%d", &size);
printf("\nEnter digits to fill the array, in numerical order: ");
for (i = 0; i < size; i++) scanf("%d", &ary[i]);
size++;
printf("\nInput x, the value to add to the array: ");
scanf("%d", &x);
while(i <= x && x > ary[i]){
i++;
j = size - 1;
while(j >= i) {
ary[j++] = ary[j];
j--;
}
}
for(i = 1; i < size; i++) {
printf("%d", &ary[i]);
}
return 0;
} //main
When it runs I get:
Enter the size of the array: 3
Enter digits to fill the array, in numerical order: 1
2
3
Input x, the value to add to the array: 4
268634426863482686352
Process returned 0 (0x0) execution time : 7.124 s
Press any key to continue.
I would examine your print function . It looks like you're printing the memory address of that particular array index rather than the value at that spot in the array.
Don't increase the size variable before you iterate through. Then walk backwards through the array, and populate as needed.
for (i = size; i >0; --i)
{
if (ary[i-1] > x)
{
ary[i] = ary[i-1];
}
else
{
ary[i] = x;
break;
}
}
if (i == 0)
ary[i] = x;
Afterwards, you can increase size as you print the output.
I've reproduced your desired output using this array walk.
There are other ways that I would solve this problem in real life, but this works well enough within your existing code.
First things first: what do you EXPECT to see as the output?
Second things first: you aren't clearing out the memory for the array before use. You have garbage values in any slots you aren't using.
Third things first: using GCC I'm seeing at least two warnings without even trying.
test.c:32:15: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
printf("%d", &ary[i]);
test.c:27:14: warning: unsequenced modification and access to 'j' [-Wunsequenced]
ary[j++] = ary[j];
In your printing loop your are not printing the value but your are printing the address of that element. Change the last loop to
for(i = 1; i < size; i++) {
printf("%d", ary[i]);
}
I am not sure why your are printing the array from index 1. But if you want to print whole array you should initialize i to zero in above loop.

a C program crashes, using a double-type variable length array

I am reading C Primer Plus these days and here is the code I wrote for the programming practice No.4 in Chapter 10, finding the index of the largest number in a double-typed array. I used variable length array in order to manually specify the array size:
#include <stdio.h>
int findmax(const double array[], int s);
//find the index of the largest number in the array
int main(void)
{
int size = 0; //size of the array
int index = 0; //index of the largest number
double num[size]; //the array holding double-type numbers
printf("Enter the size of the array: ");
scanf("%d", &size);
printf("Enter %d numbers: ", size);
for (int i = 0; i < size; i++)
scanf("%lf", &num[i]);
index = findmax(num, size);
printf("The index of the max number in the array is: %d\n", index);
return 0;
}
int findmax(const double array[], int s)
{
int index = 0;
double max = array[0];
for (int i = 0; i < s; i++)
if (array[i] > max)
{
max = array[i];
index = i;
}
return index;
}
This piece of program compiles normally, using MinGW (assume the program file name is prog.c):
gcc prog.c -o prog.exe -std=c99
The program works fine when the "size" varialbe is less than 5. But when I enter 6 or larger numbers for the "size" varialbe, the program crashes during runtime.
Loosely translated, the error message is:
the memory 0x00000038 used by 0x77c1c192 could not be "written".
I tried to eliminate the use of variable length array, the program seems to work fine. But I still couldn't get where is wrong with the original one.
Size is 0 when you allocate num. You get access violation later on because you try to acces num[0] which has not been allocated.
EDIT: I propose to use dynamic memory or declare num after size is read.
Put the statment double num[size]; after taking input of size from user for size variable.
The program works fine when the "size" varialbe is less than 5. This is the most dangerous kind of programming error -- one that appears to work fine but really does not. By writing into your array, you're immediately writing into memory that is claimed for some other purpose, because your array has no length at all. You cannot just change the size of your array by changing the size variable after the fact.
One option is to determine size before you declare the array. Another is to perform a dynamic allocation using new, but you'll get into that in several chapters, I'm sure.
int size = 0; //size of the array
int index = 0; //index of the largest number
double num[size]; //the array holding double-type numbers
printf("Enter the size of the array: ");
scanf("%d", &size);
When you first declare num array, it's size would be zero, as this is the value of size when that line is executed, although you maybe reading the value of size again later on.
When you are creating an array, the size of the array will be zero as already pointed out by others. So, when you try to fill elements into the array, there is no memory available and it overwrites into some other memory eventually leading to a memory corruption.
You can rewrite the code as below to avoid the problem.
int size = 0; //size of the array
int index = 0; //index of the largest number
double *num = NULL; //Change it to a pointer
printf("Enter the size of the array: ");
scanf("%d", &size);
num = malloc(size * sizeof(double));
if(NULL == num)
{
printf("Malloc Failed\n");
return 0;
}
printf("Enter %d numbers: ", size);
for (int i = 0; i < size; i++)
scanf("%lf", &num[i]);
or
int size = 0; //size of the array
int index = 0; //index of the largest number
printf("Enter the size of the array: ");
scanf("%d", &size);
double num[size]; //Now, num will have proper size
printf("Enter %d numbers: ", size);
for (int i = 0; i < size; i++)
scanf("%lf", &num[i]);
Here's a link to an informative article about C99's variable length arrays which talks about some potential problems which C99's variable length arrays can cause.
As others have suggested, using malloc() is the correct way to do this. Other than that, you can just make your array an arbitrary large size, and stop accepting input once it's full.

scanf infinite loop

This program takes the first number in a file and indicates how many numbers are going to be after it, then does various other things with the numbers that follow.
It seems like scanf is causing an infinite loop when trying to read from the file. WHen I run the program not even the check at 1 works
Here is the code:
#include <stdio.h>
int main(void) {
int N, a, n;
int x=0;
int t=0;
printf("1"); //Check
scanf("%d", &N);
printf("2"); //Check
int nums[N];
int i;
printf("%d", &N); //Check
for (i=0; i<N; i++)
{
scanf("%d", &nums[i]);
t+=nums[i];
if (nums[i] > x) x=nums[i];
if (i=0 || nums[i] < n) n = nums[i];
}
a = t/N;
printf("Number Processed: \t%d\n", &N);
printf("Maximum: \t%d\n", &x);
printf("Minimum: \t%d\n", &n);
printf("Total: \t%d\n", &t);
printf("Average: \t%d\n", &a);
}
The way i run the program is
gcc -lab16
./a.out <in1
where in1 is text and has the numbers
7
6
-30
90
3903
-934
443
445
Thanks for your time.
if (i=0 || nums[i] < n) n = nums[i];
you are assigning i = 0, so the loop never realy advances! You probably wanted i == 0. This is causing the infinite loop.
Other issue: int nums[N]; - if you want an array of dynamic [determined in run-time] size, you will probably need to malloc() it.
Update: note that int nums[N] is valid in C99, so if your assigment is assuming C99 you should not worry about this issue. Otherwise - malloc() will be needed:
int* nums = (int*) malloc(sizeof(int) * N)
And don't forget to free(nums) before the program ends, or you will get memory leak.
if (i=0 || nums[i] < n) n = nums[i];
This is the culprit. You are making an assignment i=0 when you should do a comparison : i==0
Your loop goes to infinity because everytime you are i to 0.
Moreover, the code you gave us, gave me an error, because you were creating new variables during runtime.
#include <stdio.h>
#include "stdlib.h"
int main(void) {
int N, a, n;
int x=0;
int t=0;
int i;
int *nums;
printf("1"); //Check
scanf("%d", &N);
printf("2"); //Check
nums = malloc(N*sizeof(int));
....
There are numerous problems with this code.
You mistook assignment for comparison:
i=0
sets i to zero. You probably meant
i==0
which checks whether i is equal to zero.
You should check the value returned by scanf(). When data read by scanf() doesn't fit the format you specified it leaves the data in the buffer and the next call to scanf() sees the same data again.
The reason that the first printf() doesn't print anything is most likely that you are not printing any newline. Note that on some output devices like terminals output is line-buffered.
You are passing a pointer to a variable to printf(), but your format specifies %d. You probably meant the variable itself, not a pointer to it.
Also, if you need an array of length dependent on a value known only at runtime, you need to allocate it on the heap, e.g. using malloc().

Resources