This question already has answers here:
Strange C code - dynamic arrays?
(4 answers)
Closed 8 years ago.
I always knew that it was not possible to build a dynamic array in C without using malloc and free, so why is this code compiling and running correctly?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a;
printf("Insert a number: ");
scanf("%d", &a);
int array[a];
int i;
for(i=0; i<a; i++)
{
array[i] = rand();
}
for(i=0; i<a; i++)
{
printf("%d\t", array[i]);
}
puts("");
return 0;
}
I understand that this is not a really dynamic array since there is no way to change the size of "array" after it has been declared, nor it can be freed callling free() but still I always thought that the size of static array must be known at compile time which is clearly not the case here..
What you are using is variable length array. Which is supported by C99 and latter. But note that VLA has automatic storage duration unlike dynamic memory allocated by malloc family functions.
Also note that compile time allocation is not equivalent to static array. static array and static allocation are different.
Related
This question already has answers here:
How to access a local variable from a different function using pointers?
(10 answers)
Closed 1 year ago.
I'm trying to setup a pointer function that returns the adress of the first element of an array which is stored locally in itself, and then use (in this case print) the contents on another function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <stdbool.h>
double *n(int a)
{
int i;
double array[' '];
for(i=0;i<a;i++)
{
array[i] = rand();
printf("\n element: %f \t\n\n", array[i]);
}
return array;
}
void exe()
{
double *unfixed;
int c, b, j;
scanf("%d", &b);
unfixed = n(b);
printf("\n\n Precoded acces value %f \n\n", *(unfixed + c));
for(j=0;j<b;j++)
{
printf("\n %f", *(unfixed + j));
}
return;
}
int main()
{
exe();
return 0;
}
It works properly when I refer to it by static statements, example:
printf("\n\n %f \n\n", *(unfixed + c));
On the contrary when I go ahead and try to get a cycle or decision to be made it just straight up doesn't work.
P.D.: Also for some unholy reason it works perfectly with int type pointer functions.
Further evidence of the psychological abuse
The function n returns a pointer to the first element of a local array with automatic storage duration that will not be alive after exiting the function. So the returned pointer is invalid. Dereferencing such a pointer invokes undefined behavior.
You could declare the array as having static storage duration
static double array[' '];
or allocate the array dynamically.
But in any case the function is unsafe because there is no check whether a is not greater than the value of the integer character literal ' ' used as the size of the array.
Also within the function exe you are using the variable c that was not initialized in this statement
printf("\n\n Precoded acces value %f \n\n", *(unfixed + c));
that again invokes undefined behavior.
Do the below codes do the exact same thing?
Code Snippet 1:
#include <stdio.h>
int main(void){
int size;
scanf("%d", &size);
int arr[size];
//code to manipulate array
return 0;
}
Code Snippet 2:
#include <stdio.h>
int main(void){
int size;
scanf("%d", &size);
int *arr = malloc(size*sizeof(int));
//code to manipulate array
free(arr);
return 0;
}
These are not the same.
The first snippet creates an array with automatic storage duration, i.e. on the stack in most implementations, while the second creates an array dynamically on the heap. The former has a lifetime of the scope than encloses it, while the latter is valid for the lifetime of the program or until it is freed, whichever comes first.
Apologies for this re-post as I do not know how to phrase my question as it is my first time using stack overflow. I hope someone could help me out in this quiz for my studies.
I had research on this program but I do not know if it relates to the quiz question on arraySize.
Question is below:
we pass array ai to function fillArray. What exactly is passed to the function? The answer is a single memory address, not the 10 integers! This is why we can use the function to fill the array ai with 10 numbers.
Complete the above function fillArray so that it reads arraySize number of integers from the user and fill the array with those numbers.
Write a driver program to test the function with integer arrays of different sizes.
Note the formal parameter int array[] in function fillArray can be changed to int *array. Verify this by modifying and testing your code.
My code is below:
#include <stdio.h>
#define MAX 10
int fillArray(int array[], int arraySize);
void print_intaray(int array[], int arraySize);
main()
{
int ai, exam_scores[MAX];
printf("***List of Array***\n\n");
ai = fillArray(exam_scores, MAX);
print_intaray(exam_scores, ai);
}
int fillArray(int array[], int arraySize)
{
int ai, count = 0;
printf("Type array, EOF to quit\n");
while ((count < arraySize) && (scanf("%d", &ai) !=EOF))
{
array[count] = ai;
count++;
}
return count;
}
void print_intaray(int array [], int arraySize)
{
int i;
printf("\n***Your Arrary***\n\n");
for (i = 0; i<arraySize; i++)
printf("%d\n", array[i]);
}
I'm new to programming and I hope my question could somehow be resolve.
Thanks for viewing :)
Assuming the question is "Why are int array[] and int *array equivalent in the function argument":
I'm not much of a C expert, but AFAIK arrays (in C) are largely just pointers to which you append a certain offset. Telling C you expect an int myarray[] means pretty much the same as expecting a pointer to an integer (int *array). If you increment the pointer, you can access the next element in the array. This is also known as pointer arithmetic.
The C compiler translates array syntax like foo[3] in the background to something like *(*foo+3), but you can also do that yourself by just dealing with the pointers.
I'm getting some input from the user in the main() function and create an array accordingly. Because of the nature of the location of this array it is not visible to other functions and I need to pass it to a few other functions for processing.
Is there any way to do this without allocating memory for it and passing a pointer to that allocated memory?
flight is structure typedef.
int main()
{
do{ // Read # of flights from user
printf("Enter max number of flights to read in from file\n");
printf("--> ");
fflush(stdin);
} while(!(scanf("%d",&num_of_flights)));
flight database[num_of_flights]; // Create database for flights
In C you can allocate memory during runtime in such way
#include <stdlib.h>
#include <stdio.h>
void print_array(int *array, int array_size){
for(int i = 0; i < array_size; ++i){
printf("%d ", *(array + i));
}
}
int main(){
int *array;
int array_size;
scanf("%d", &array_size);
array = malloc(sizeof(int) * array_size);
// Fill array with ints
for(int i = 0; i < array_size; i++){
*(array + i) = i;
}
print_array(array, array_size);
return 0;
}
This shows how you might use malloc on a struct and then use the malloc'd item as a parameter to other functions
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct fl {
int distance;
char aeroplane[30];
char startgeo[2];
};
typedef struct fl flight;
void show_flight_data(flight d) {
printf("distance %d aeroplane %s",d.distance, d.aeroplane);
}
int main()
{
int num_of_flights;
flight *database;
do{ // Read # of flights from user
printf("Enter max number of flights to read in from file\n");
printf("--> ");
fflush(stdin);
} while(!(scanf("%d",&num_of_flights)));
database=(flight *)malloc(sizeof(flight) * num_of_flights);
database[0].distance = 100;
database[1].distance = 200;
strcpy(database[0].aeroplane, "777");
strcpy(database[1].aeroplane, "Airbus");
show_flight_data(database[0]);
return(0);
}
From the C standard, 6.2.4 Storage durations of objects:
The lifetime of an object is the portion of program execution during
which storage is guaranteed to be reserved for it. An object exists,
has a constant address) and retains its last-stored value
throughout its lifetime....
An object whose identifier is declared with no linkage and without the
storage-class specifier static has automatic storage duration...
For such an object that does not have a variable length array type,
its lifetime extends from entry into the block with which it is
associated until execution of that block ends in any way.
So, the lifetime of database extends until the execution of its enclosing block ends. That block is the body of main, so it is alive until main returns or the program exits. Therefore, you can simply pass database to other functions, or even store its address in a global that is accessed by other functions ... there is no need to allocate space and copy it.
BTW, you should be aware that by defining database[num_of_flights], where num_of_flights is not a constant, you are using a relatively recent feature of C -- variable length arrays (VLA's) -- and that some prominent C compilers (cough, Visual Studio, cough) do not support them.
Write a program to manipulate the temperature details as given below.
- Input the number of days to be calculated. – Main function
- Input temperature in Celsius – input function
- Convert the temperature from Celsius to Fahrenheit.- Separate function
- find the average temperature in Fahrenheit.
how can I make this program without initial size of array ??
#include<stdio.h>
#include<conio.h>
void input(int);
int temp[10];
int d;
void main()
{
int x=0;
float avg=0,t=0;
printf("\nHow many days : ");
scanf("%d",&d);
input(d);
conv();
for(x=0;x<d;x++)
{
t=t+temp[x];
}
avg=t/d;
printf("Avarage is %f",avg);
getch();
}
void input(int d)
{
int x=0;
for(x=0;x<d;x++)
{
printf("Input temperature in Celsius for #%d day",x+1);
scanf("%d",&temp[x]);
}
}
void conv()
{
int x=0;
for(x=0;x<d;x++)
{
temp[x]=1.8*temp[x]+32;
}
}
In C arrays and pointers are closely related. In fact, by design an array is just a syntax convention for accessing a pointer to an allocated memory. *(see note for more details below)
So in C the statement
anyarray[n]
is the same as
*(anyarray+n)
Using pointer arithmetic.
You don't really have to worry about the details to make it "work" as it is designed to be somewhat intuitive.
Just create a pointer, and allocate the memory and then access it like as an array.
Here is some examples --
int *temp = null; // this will be our array
// allocate space for 10 items
temp = malloc(sizeof(int)*10);
// reference the first element of temp
temp[0] = 70;
// free the memory when done
free(temp);
Remember -- if you access outside of the allocated area you will have unknown effects.
To be clear it is the indexing operator ([ ]) that is translated to pointer arithmetic. This is not an array in the modern sense of the
type. Whether (or not) the pointer involved points to (dynamically) allocated
memory is inconsequential to how this operator works. In a more modern language you would be able to operate on the array as an abstract type (to see how big it is, for example), you can't do this in C.
An array without an initial size is basically just a pointer. In order to dynamically set the size of the array, you need to use the malloc() or calloc() functions. These will allocate a specified amount of bytes of memory.
In your code above, declare temp as an int pointer
int *temp;
Then allocate space for it using malloc() or calloc(). The argument that these functions take is is the number of bytes of memory to allocate. In this case, you want enough space for d ints. So...
temp = malloc(d * sizeof(int));
malloc returns a pointer to the first byte in the block of memory that was just allocated. Regular arrays are simply pointers to the first byte in a sectioned off block of memory, which is exactly what temp is now. Thus, you can treat the temp pointer as an array! Like so:
temp[1] = 10;
int foo = temp[1];
printf("%d", foo);
Outputs
10
You will need to declare temp as an int pointer (instead of an int array). Then, you can use malloc in your main (after your first scanf):
temp = malloc(d * sizeof(int));
If your compiler supports c99, then simply use VLA(variable length array).Use like this:
void input(int);
int d;
void main()
{
int x=0;
float avg=0,t=0;
printf("\nHow many days : ");
scanf("%d",&d);
int temp[d];
input(d);
conv();
for(x=0;x<d;x++)
{
t=t+temp[x];
}
avg=t/d;
printf("Avarage is %f",avg);
getch();
}
Now temp[] is defined inside main() after date input.
1-add #include<stdlib.h> at the top of your file. Then modify the conv() code as follows:
2- modify temp declaration as follows (global variable):
int *temp;
3- modify input(int d) function as follows (tested on Visual Studio 2010):
void input(int d)
{
int x=0;
temp=(int*)malloc(sizeof(int)*d);
for(x=0;x<d;x++)
{
printf("Input temperature in Celsius for #%d day",x+1);
scanf("%d",&temp[x]);
}
}
Allocate the "array" dynamically on the heap after you read the size.
I didn't change anything else so you may see it clearly.
#include<stdio.h>
#include<conio.h>
#include <stdlib.h> //here
void input(int);
int *temp=0; //here
int d;
void main()
{
int x=0;
float avg=0,t=0;
printf("\nHow many days : ");
scanf("%d",&d);
temp=malloc(d * sizeof(int)); //here
input(d);
conv();
for(x=0;x<d;x++)
{
t=t+temp[x];
}
avg=t/d;
printf("Avarage is %f",avg);
getch();
}
void input(int d)
{
int x=0;
for(x=0;x<d;x++)
{
printf("Input temperature in Celsius for #%d day",x+1);
scanf("%d",&temp[x]);
}
}
void conv()
{
int x=0;
for(x=0;x<d;x++)
{
temp[x]=1.8*temp[x]+32;
}
}
Maybe it's late to answer but...
If you work with small embedded system you might not have malloc and free functions.
So you have to sacrifice memory for 366 * sizeof(your_type), define it statically and use as a circular buffer. Then you can always slice it by number of days you need to calculate an average value.
Of course this makes natural constrains. You can define it by yourself.