defining a global struct pointer in C? - c

I need to identify a global struct (array), consisted of 4 integers.
The problem is, size of that struct array is not known in advance.
I'm trying to make sth. like this:
typedef struct
{
int value;
int MAXleft;
int MAXright;
int MAX;
} strnum;
int main ()
{
int size;
scanf("%d", &size);
strnum numbers[size];
return 0;
}
I heard that, it is possible to do this by pointers but I don't know how to do.

You can allocate the space for several structures dynamically like this:
strnum *numbers = malloc( size * sizeof(strnum) );
Then you can use it like any regular array (mostly).
It might be more convenient to use calloc instead of malloc. It allocates a number of blocks and fills them with zeros. Please note, that malloc doesn't clear allocated memory.
strnum *numbers = calloc( size, sizeof(strnum) );
When you are done with the memory don't forget to call free( numbers ), which will return the allocated memory back to a memory manager.
If you don't free it when it's no longer required and allocate some more and more, a memory footprint of the program will grow for no good reason as the program continues to work. This is called a memory leak and should be avoided. It might eventually result in the lack of memory for a program and unpredictable results.
And don't forget to include a stdlib.h header with prototypes of memory allocation functions.

You can start with malloc() and then do realloc() when the size keeps increasing.
I would suggest you to allocate a pool of 10 structures at once so that the number of calls to realloc() are reduced.

It is called Dynamic Memory Allocation
The thing you are trying to do can be done as follows:
strnum* number;
int size = 0;
scanf("%d",&size);
number = malloc(size * sizeof(strnum));
Also, don't forget to free the memory once you have done using the array.
free(number);

Related

Is it possible to increase char array while using it, WITHOUT malloc?

I have a char array, we know that that a char size is 1 byte. Now I have to collect some char -> getchar() of course and simultaneously increase the array by 1 byte (without malloc, only library: stdio.h)
My suggestion would be, pointing to the array and somehow increase that array by 1 till there are no more chars to get OR you run out of Memory...
Is it possible to increase char array while using it, WITHOUT malloc?
No.
You cannot increase the size of a fixed size array.
For that you need realloc() from <stdlib.h>, which it seems you are not "allowed" to use.
Is it possible to increase char array while using it, WITHOUT malloc?
Quick answer: No it is not possible to increase the size of an array without reallocating it.
Fun answer: Don't use malloc(), use realloc().
Long answer:
If the char array has static or automatic storage class, it is most likely impossible to increase its size at runtime because keeping it at the same address that would require objects that are present at higher addresses to be moved or reallocated elsewhere.
If the array was obtained by malloc, it might be possible to extend its size if no other objects have been allocated after it in memory. Indeed realloc() to a larger size might return the same address. The problem is it is impossible to predict and if realloc returns a different address, the current space has been freed so pointers to it are now invalid.
The efficient way to proceed with this reallocation is to increase the size geometrically, by a factor at a time, 2x, 1.5x, 1.625x ... to minimize the number of reallocations and keep linear time as the size of the array grows linearly. You would a different variable for the allocated size of the array and the number of characters that you have stored into it.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *a = NULL;
size_t size = 0;
size_t count = 0;
int c;
while ((c = getchar()) != EOF && c != '\n') {
if (count >= size) {
/* reallocate the buffer to 1.5x size */
size_t newsize = size + size / 2 + 16;
char *new_a = realloc(a, new_size);
if (new_a == NULL) {
fprintf("out of memory for %zu bytes\n", new_size);
free(a);
return 1;
}
a = new_a;
size = new_size;
}
a[count++] = c;
}
for (i = 0; i < count; i++) {
putchar(a[i]);
}
free(a);
return 0;
}
There are two ways to create space for the string without using dynamic memory allocation(malloc...). You can use a static array or an array with automatic storage duration, you need to specify a maximum amount, you might never reach. But always check against it.
#define BUFFER_SIZE 0x10000
Static
static char buffer[BUFFER_SIZE];
Or automatic (You need to ensure BUFFER_SIZE is smaller than the stack size)
int main() {
char buffer[BUFFER_SIZE];
...
};
There are also optimizations done by the operating system. It might lazily allocate the whole (static/automatic) buffer, so that only the used part is in the physical memory. (This also applies to the dynamic memory allocation functions.) I found out that calloc (for big chunks) just allocates the virtual memory for the program; memory pages are cleared only, when they are accessed (probably through some interrupts raised by the cpu). I compared it to an allocation with malloc and memset. The memset does unnessecary work, if not all bytes/pages of the buffer are accessed by the program.
If you cannot allocate a buffer with malloc..., create a static/automatic array with enough size and let the operating system allocate it for you. It does not occupy the same space in the binary, because it is just stored as a size.

Letting the user define size of an array

How can I let the user choose a number say n and then create an array with the size of n?
Can I just say int a[]=malloc (n*sizeof(int))?
There are two ways to do that. If the array size is small then you can use variable length array
/* Valid in C99 and later */
int n;
scanf("%d", &n);
int a[n];
This will allocate memory on stack. Other way is you can use dynamic memory allocation which will allocate memory on the heap
int *a = malloc(n*sizeof(int));
Your idea is nearly correct:
int a[] = malloc(n*sizeof(int));
Using malloc is the correct way.
But you cannot assign the returned address to an array.
You must use a pointer variable instead:
int *a = malloc(n*sizeof(int));
Yes if u want to set the size of the array at run-time.
Then u should go for dynamic memory allocation(malloc/calloc).
int a[]=malloc (n*sizeof(int));//this not possible.
int *a =malloc (n*sizeof(int)); // this is possible.
There are two basic ways for allocating the memory to create an array where the size to the array is determined as input:
The first one is,
allocating the memory for array in the 'stack' segment of memory where the size of array is taken as input ant then the array of that particular size is defined and granted memory accordingly.
int n;
scanf("%d",&n); //scanning the size
int arr[n]; //declaring the array of that particular size here
The second one is,
allocating the required memory in the 'heap' segment of memory.It is the memory allocated during runtime (execution of the program)
So,another way of declaring an array where size is defined by user is
int n,*arr;
scanf("%d",&n);
arr=malloc(n*sizeof(int)); //malloc function provides a contiguous space
or
arr=calloc(n,sizeof(int)); //calloc function is similar,initializes as 0
to use both these functions make sure to include stdlib.h.
Variable length arrays (VLAs) were added to C with C99, but made optional with C11. They are still widely supported, though. This is the simplest way to define an array with user-selected size at runtime.
Other than that VLAs may not be available on all platforms, they also may fail silently when there is an allocation failure. This is a disadvantage that malloc() avoids when used correctly.
You can't assign to an array in C, and instead you need to store the value returned by malloc() in a pointer. Note that malloc() returns NULL when there is an allocation failure, allowing code to check for failure and proceed accordingly. The actual allocation might look like this:
int *a_dyn = malloc(sizeof *a_dyn * arr_sz);
This is an idiomatic way of calling malloc(). Note that there is no need to cast the result of malloc(), and note that the operand to sizeof is not an explicit type, but rather an expression involving a_dyn. The sizeof operator uses the type of the expression *a_dyn, which is in fact int (there is no dereference made). This is less error-prone and easier to maintain when types change during the life of a program than coding with explicit types. Also note that the sizeof expression comes before arr_sz. This is a good practice to follow: sometimes you might have a call like:
int *arr = malloc(sizeof *arr * nrows * ncols);
Placing sizeof first forces the multiplication to be done using size_t values, helping to avoid overflow issues in the multiplication.
Don't forget to free any memory allocated with malloc() when it is no longer needed, avoiding memory leaks.
Whether you use a VLA or malloc(), you must validate user input before using it to avoid undefined behavior. Attempting to allocate an array of non-positive size leads to undefined behavior, and attempting to allocate too much memory will lead to an allocation failure.
Here is an example program that illustrates all of this:
#include <stdio.h>
#include <stdlib.h>
#define ARR_MAX 1024 // some sensible maximum array size
int main(void)
{
int arr_sz;
int ret_val;
/* validate user input */
do {
printf("Enter array size: ");
ret_val = scanf("%d", &arr_sz);
} while (ret_val != 1 || arr_sz < 1 || arr_sz > ARR_MAX);
/* use a VLA */
int a_vla[arr_sz];
for (int i = 0; i < arr_sz; i++) {
a_vla[i] = i;
printf("%d ", a_vla[i]);
}
putchar('\n');
/* use malloc() */
int *a_dyn = malloc(sizeof *a_dyn * arr_sz);
if (a_dyn == NULL) { // malloc failure?
fprintf(stderr, "Unable to allocate memory\n");
} else { // malloc success
for (int i = 0; i < arr_sz; i++) {
a_dyn[i] = i;
printf("%d ", a_dyn[i]);
}
putchar('\n');
}
/* avoid memory leaks */
free(a_dyn);
return 0;
}

C - Dynamically sized array of struct pointers without using realloc?

I need help with a school assignment, specifically with resizing the amount of memory allocated for a pointer WITHOUT realloc.
I have the following declarations in my program.
struct GraphicElement
{
enum{ SIZE = 256 };
unsigned int numLines;
Line* pLines;
char name[SIZE];
};
typedef struct
{
unsigned int numGraphicElements;
GraphicElement* pElements;
}VectorGraphic;
VectorGraphic Image;
As the program runs I'll be adding more GraphicElements to pElements.
For example, after 5 iterations the memory for pElements should be something like this:
[GraphicElement 0][GraphicElement 1] ... [GraphicElement 4]
For the function AddGraphicElement(VectorGraphic* vg) I have this code (with some lines removed for easier reading):
vg->pElements = (GraphicElement*)realloc(vg->pElements, sizeof(GraphicElement)*(vg->numGraphicElements+1));
//Then I assign inputs from user into the members of the struct at vg->pElements[vg->numGraphicElements]
vg->numGraphicElements++;
This works, BUT according to the instructions given by my professor, I'm only allowed to use malloc and free- no realloc. Sadly the only way I've made this work is with realloc.
Can anyone point me in the right direction to implement this using only malloc?
Thanks!
If you are not allowed to use realloc, but malloc and free are allowed, you can replace the call with the following, less efficient, sequence:
void *newData = malloc(newSize);
memcpy(newData, oldData, oldSize);
free(oldData);
Internally, realloc does the same thing, but it does so more efficiently. Unlike user program, realloc knows the actual size of the dynamic memory chunk, so it checks if newSize <= actualSize to avoid reallocation. When actualSize is insufficient, realloc does the same thing as above. realloc has additional logic to deal with situations when the size need to shrink, but in your situation this does not apply.

Dynamic memory allocation in for loop

I'm allocating memory using malloc:
main()
{
int *array;
int i;
for(i = 0; i<40; i++)
{
array = malloc(100 * sizeof(int));
}
free(array);
}
This should allocate 15.625KB but if i run this same in valgrind, peak memory is 15.92KB. How it comes?
How to free all 40 pointers?
malloc always allocates a bit more than you asked for, necessary for internal accounting, caused by fragmentation, etc.
At a minimum - the size of each allocated block need to be stored somewhere, often some pointers (e.g. to the next allocated/free block) are also stored, and in some cases (e.g. debug builds) additional debugging information is also stored. Most implementation store as much information as possible in the unallocated space, so only a few bytes (e.g. size) would be stored in each allocated block.
As to fragmentation, many implementations have a minimal allocated size or round up the requested size to maintain some kind of alignment.
Regarding freeing all 40 pointers, you could for example have an array of pointers holding the pointers returned from malloc and go over it at the end of your function.
Something along the lines of:
main()
{
int *arrays[40];
int i;
for(i = 0; i<40; i++)
{
arrays[i]=malloc(100 * sizeof(int));
}
for(i = 0; i<40; i++)
{
free(arrays[i]);
}
}
free (array) should be inside the loop to free all pointers instead of the last one only.
When you call malloc(),The amount of memory actually used is slightly more than what is requested.This extra includes information that records how big the block is, where is next free block available etc.
This extra information is the reason so that free() function knows how much to free.

char pointer is struct array memory leak

I'm having memory leaks in a larger program and I believe this is the cause of it.
#include <stdlib.h>
#include <Windows.h>
typedef struct _struct{
char* name;
} str;
int main() {
system("PAUSE");
str* Character = (str*)malloc(sizeof(str) * 20000);
for(int i = 0; i < 20000; i++){
Character[i].name = (char*)malloc(20000); // Assign memory.
}
for(int i = 0; i < 20000; i++){
free(Character[i].name); // Free memory.
}
free(Character);
system("PAUSE");
}
Memory at first pause: ~500K.
Memory at second pause: ~1.7M.
Using VS2012 for testing. Any ideas?
How are you measuring the amount of memory occupied by the program? One thing off the top of my head is that you're looking at the size of the working set the OS is keeping track of. Since you've allocated and freed a lot of memory, the size of that set has increased. Some OSs will adjust the size of the working set after a while, some won't. What OS are we looking at here?
When you call malloc, memory is allocated on the heap. If there is insufficient space left on the heap, the program will ask the OS for more memory and another chunk is acquired. Memory acquired from the OS is usually not returned until the program finishes (although this is up to the OS).
Program size alone can not normally be used to check for memory leaks! Use Valgrind or a similar tool to check for memory that never gets freed.
str* Character = (str*)malloc(sizeof(str) * 20000);
In the above line you are allocating the memory by finding the size of the struct. Here the size of the structure you will get will be the size of the pointer width and not the size of the char.
suppose for example if the pointer width is 32 bit the it will allocate (4 * 20000) = 80000 bytes.
If you want to allocate for 20000 struct's,
str* Character = (str*)malloc(sizeof(char) * 20000);

Resources