Array of runtime size and frame size deduction - c

Code:
#include <stdio.h>
int main() {
int size;
scanf("%d", &size);
int foo[size];
for(int i = 0; i < size; i++)
scanf("%d", &foo[i]);
for(int i = 0; i < size; i++)
printf("%d\n",foo[i]);
return 0;
}
How does this code compile? More specifically: how does the compiler know what is the size of frame main if size of local variable foois not known at compile time. I was expecting a compile error along the lines: "foo has incomplete type"
To have also tried the code and it also runs fine:

In your code, you will first read data to specify size of array elements and then it will allocate that array on stack.
This approach is available from C99.
How compiler knows the size? It doesn't know. if you will enter too big value for size you may get stack overflow.
It will compile in a way that it will make sure to create as big push as required to put entire array to stack according to variable of size multiplied by size of single array element:
stack_size_usage = size * sizeof (int)
In C89, this would reproduce error as all variables must be first initialized before any code can be executed.
I would instead use HEAP memory for this type of allocation.
#include <stdio.h>
int main() {
int size;
int* foo;
scanf("%d", &size);
foo = malloc(sizeof(*foo) * size);
if (!foo) { /* failed, stop program */ }
for(int i = 0; i < size; i++)
scanf("%d", &foo[i]);
for(int i = 0; i < size; i++)
printf("%d\n",foo[i]);
free(foo);
return 0;
}

Related

How can static array in C taking size in runtime?

I am mindblown by this small code:
#include <stdio.h>
int main()
{
int limit = 0;
scanf("%d", &limit);
int y[limit];
for (int i = 0; i<limit; i++ ) {
y[i] = i;
}
for (int i = 0; i < limit; i++) {
printf("%d ", y[i]);
}
return 0;
}
How on earth this program is not segment-faulting as limit (size of the array) is assigned at runtime only?
Anything recently changed in C? This code shouldn't work in my understanding.
int y[limit]; is a Variable Length Array (or VLA for short) and was added in C99. If supported, it allocates the array on the stack (on systems having a stack). It's similar to using the machine- and compiler-dependent alloca function (which is called _alloca in MSVC):
Example:
#include <alloca.h>
#include <stdio.h>
int main()
{
int limit = 0;
if(scanf("%d", &limit) != 1 || limit < 1) return 1;
int* y = alloca(limit * sizeof *y); // instead of a VLA
for (int i = 0; i<limit; i++ ) {
y[i] = i;
}
for (int i = 0; i < limit; i++) {
printf("%d ", y[i]);
}
} // the memory allocated by alloca is here free'd automatically
Note that VLA:s are optional since C11, so not all C compilers support it. MSVC for example does not.
This doesnt compile in visual studio because limit "Error C2131 expression did not evaluate to a constant"
If you make limit a constexpr though then the compiler will not mind because youre telling it it wont change. You cant use 0 though as setting an array to a constant size length zero is nonsence.
What compiler does this run on for you ?

Segmentation fault (core dump) but don't know how to fix it

When trying to input a string of chars, i get a warning
warning: 'doc' may be uninitialized in this function [-Wmaybe-uninitualized]
When i run the code, it only allows me to enter the string itself and then it stops.
I tried compiling the code using an online compiler and it returned `segmentation fault (core dumped). I know something is wrong but i don't know how to fix it.
#include <stdio.h>
#include <string.h>
typedef struct Pacient{
char ime_prezime[100];
int osiguruvanje;
int broj_pregledi;
}Pacient;
typedef struct MaticenDoktor{
char ime_prezime[100];
int broj_pacienti;
Pacient pacient[200];
float cena;
}MaticenDoktor;
void najuspesen_doktor(MaticenDoktor *doc, int n){
int i, j, najgolema_zarabotka=0, najmnogu_pregledi=0, zarabotka, pregledi;
char najuspesen[100];
for(i=0; i<n; i++){
zarabotka=0;
pregledi=0;
for(j=0; j<doc[i].broj_pacienti; j++){
if(doc[i].pacient[j].osiguruvanje==0){
zarabotka+=doc[i].cena;
pregledi++;
}
}
if(zarabotka>najgolema_zarabotka){
najgolema_zarabotka=zarabotka;
strcpy(najuspesen, doc[i].ime_prezime);
najmnogu_pregledi=pregledi;
}
else if(zarabotka==najgolema_zarabotka){
if(pregledi>najmnogu_pregledi){
najgolema_zarabotka=zarabotka;
strcpy(najuspesen, doc[i].ime_prezime);
najmnogu_pregledi=pregledi;
}
}
}
printf("%s %d %d", najuspesen, najgolema_zarabotka, najmnogu_pregledi);
}
int main()
{
int i, j, n;
printf("Vnesi broj na doktori\n");
scanf("%d", &n);
MaticenDoktor *doc;
for(i=0; i<n; i++){
scanf("%s", doc[i].ime_prezime); // <---- warning here
scanf("%d", &doc[i].broj_pacienti);
scanf("%f", &doc[i].cena);
for(j=0; j<doc[i].broj_pacienti; j++){
scanf("%s", doc[i].pacient[j].ime_prezime);
scanf("%d", &doc[i].pacient[j].osiguruvanje);
scanf("%d", &doc[i].pacient[j].broj_pregledi);
}
}
najuspesen_doktor(doc, n);
return 0;
}
Does anyone know how to fix this?
MaticenDoktor *doc; only declares a pointer, and not the full structure (or the array). You need to initialize it to point to somewhere, where you can warrant there's enough free memory to hold the information. You can ensure this in several ways:
You can, instead, hold a complete structure in the function body (main in your case, with this similar declaration:
MaticenDoktor doc; /* no pointer, but a full structure variable is declared */
scan("%s", doc.ime_prezime);
...
You can, declare an array of MaticenDoktor structures with the following code:
MaticenDoktor doc[100]; /* now doc is an array with space for 100 MaticenDoktors */
scan("%s", doc[n].ime_prezime); /* n ranges from 0 to 99 max */
You can, if you don't know a priori how many MaticenDoktor you are going to have, and you read it before the loop, with:
MaticenDoktor *doc = malloc(n * sizeof *doc); /* you have doc pointing to an array of n MaticenDoktors */
scan("%s", doc[n].ime_prezime);
...
free(doc); /* after you are completely finished using doc */
You can, if you are short of memory, just declare an array of pointers with space for the maximum, and allocate the structures as you need them:
MaticenDoktor *doc[1000]; /* space for maximum of 1000 pointers to MaticenDoktor */
for (i = 0; i < n && i < 1000; i++) {
doc[i] = malloc(sizeof *doc[i]); /* size of pointed value, not of pointer */
scanf("%s", doc[i]->ime_prezime);
...
}
and later on
for (i = 0; i < n && i < 1000; i++) {
free(doc[i]); /* free space used by doc[i] */
}
... and many other ways to organize your memory :)
doc has not been assigned so points to an unpredictable location. You should either place it on the stack:
assing dynamic memory first.
MaticenDoktor *doc;
int len = 10; // all memory that you need.
doc =(MaticenDoktor *)malloc(sizeof(MaticenDoktor)*len);
it fix the Warning .

struct segmentation fault gcc on raspberry pi

I'm struggling with a small amount of C code trying to get to run on a RPI2b.
The code is about creating a struct including a integer array with a dynamic size.
The struct file has to be declared as a pointer in my main function.
This is because: The bigger purpose of my program will be executing three Array iterations in parallel by the use of pthread.
As far as I know pthread needs a pointer in function call.
I don't want to change anything by using pthread (never change a winning team).
This is what my code snipping should do:
define a STEP number
declare a static int array with defined amount of STEP
declare a struct including a dynamic array
fill up the static int array
allocate memory for dynamic array
fill up dynamic array with values of static int array
print both on console
No errors while compiling with gcc!
The Problem is that when it Comes to allocate memory for the dynamic array program simply pints a "Segmentation fault" on the console.
The fun fact is: I've copied paste the whole code to Visual Studio 2017 and it works perfectly fine!
Here is my code:
#include<stdio.h>
#include<stdlib.h>
#define STEPS 50 //defined steps
typedef struct file File;
struct file {
int type;
int* array; //dynamic array
};
int main(void) {
int i = 0;
int mainarray[STEPS] = { 0 };
struct file *f = (File*)malloc(sizeof(File)); //allocate memory for struct
printf("Fill up static array\n");
for (i = 0; i <= STEPS; i++) {
mainarray[i] = i;
}
printf("static array values:\n");
for (i = 0; i <= STEPS; i++) {
printf("%d\n", mainarray[i]);
}
printf("allocate memory for dynamic array\n");
f->array = (int*)malloc(sizeof(int) * STEPS); //Here I receive my segmentation fault
if (f->array == NULL) {
printf("allocating error\n");
}
for (i = 0; i <= STEPS; i++) {
f->array[i] = 20000 * mainarray[i];
}
printf("compare of arrays\n");
for (i = 0; i <= STEPS; i++) {
printf("i:=\t%d\tMainarray:\t%d\tStructarray:\t%d\t\n", i, mainarray[i], f->array[i]);
}
free(f->array);
free(f);
}
Your problem is (see comment from Some Programmer Dude) that you go out of bounds of your array. That causes undefined behavior, in your case resulting in a seg fault.
for (i = 0; i <= STEPS; i++)
should be:
for (i = 0; i < STEPS; i++)
because STEPS-1 is the last valid array element.

fread'ing a binary file into a dynamically allocated C array

Just a quick comment to start: While there are similar threads to this one, I haven't quite been able to find the solution I'm looking for. My problem is the following:
I have 2D arrays of doulbes saved to binary files and I would like to read the binary files (using C code) into a 2D array. Additionally, I need to allocate the memory dynamically as the shape of the arrays will be changing in my application. To get started, I tried the following code:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
int N = 10; //number of rows of 2D array
int M = 20; //number of columns
/* first allocate the array */
double **data;
data = (double **)malloc(N*sizeof(double *));
for(unsigned int i=0; i < N; i++) {
data[i] = (double *)malloc(sizeof(double)*M);
}
FILE *ptr;
ptr = fopen("random_real_matrix.dat", "rb");
fread(data, sizeof(data), 1, ptr);
for(unsigned int i=0; i<10;i++){
for(unsigned int j=0; j<20;j++){
fprintf(stderr, "m[%d][%d] = %f\n ", i, j, data[i][j]);
}
}
}
Unfortunately, this code segfaults. I checked to see if I can set the array entries like
d[0][0] = 235;
and that works fine.
Assuming this approach can be fixed, I'm also interested to know if it could be extended to read to an array of double complex's.
Any advice would be greatly appreciated!
Your fread statement is incorrect. It's a common beginner mistake to think that sizeof gets the size of a dynamically allocated array. It doesn't. In this case it just returns the size of a double **. You will need to read in each double in the file and put that into the correct spot in the array.
for (int ii = 0; ii < N; ++ii)
{
for (int jj = 0; jj < M; ++jj)
{
fread(data[ii][jj], sizeof(double), 1, ptr);
// Be sure to check status of fread
}
}
You can do this with a single for loop (or a single fread) but this is probably clearer to read.
Because you allocated each row separately, you can't read into the entire array at once. You need to do it row by row.
for (int i = 0; i < N; i++) {
fread(data[i], sizeof(double), M, ptr);
}

Segmentation fault (core dumped): scanf int data to array with C

Are there any limitations when implementing scanf int data type to an array in C? The code below gives me a "segmentation fault(core dumped) when array has more than 6 indices.
====example code=========
#include <stdio.h>
int main(void)
{
int size;
int array[size];
int x;
scanf("%d", &size);
for(x = 0; x < size; x++){
scanf("%d", &array[x]);
}
for(x = 0; x < size; x++){
printf("[%d] ", array[x]);
}
}
input:
4
3 45 5 76
output:
[3] [45] [5] [76]
input:
7
34 2 5 6 9 3 8
output:
Segmentation fault(core dumped)
My goal is to have a dynamic array. The user will decide its size. So far this proves impossible. I understand the dynamic array approach can be implemented with struct or c++ vector. However, I would like to understand whether the error is due to the code structure or am I ignorant of certain limitation in the C array.
I look forward to your knowledgeable input.
I am going to point out 2 things
Write int array[size]; after scanf statement and include stdlib.h in your code. In the new versions of gcc compiler takes care of memory allocation and finally freeing it for you. Also return some value as your return type is int.
But my advise to you is that use malloc statement in the following fashion as you might need to run the code on older version of gcc. And also compiler internally does the same thing.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int size;
scanf("%d", &size);
int *array;
array=malloc(size*sizeof(int));
int x;
for(x = 0; x < size; x++){
scanf("%d", &array[x]);
}
for(x = 0; x < size; x++){
printf("[%d] ", array[x]);
}
free (array);
return 0;
}
int size;
int array[size];
size is uninitialized right now . Array of what size would be created ?
Declare array after scanf("%d",&size).
The "classic" way would be to allocate memory for your array, either using malloc(size * sizeof(int)) or by using calloc(size, sizeof(int)). The former makes no guarantees as to the state of the memory allocated (apart from "allocated"), the latter guarantees that the memory has been zeroed before the function returns.
You can not use array[size] when size is not defined yet ! Instead if you want to use a dynamic array, you can do it like this:
#include <stdio.h>
#include <stdlib.h>
void main()
{
int size;
int *array;
int x;
if (scanf("%d", &size)==1){
array=calloc(size*sizeof(int));
}
//check if allocation has been done
for(x = 0; x < size; x++){
scanf("%d", &array[x]);
}
for(x = 0; x < size; x++){
printf("[%d] ", array[x]);
}
free(array);
return;
}
Better you dynamically allocate memory for taking a user input size.
int *arr,size;
scanf("%d",size);
arr=(int *)malloc(sizeof(int)*size);
This will create an integer array of length "size".

Resources