Question

I am trying to learn dynamic memory allocation and structures and I have some questions.

First of all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int *number;
    number = malloc(1*sizeof(int));
    int a;
    for(a=0;a<150;a++)
    {
        number[a]=a;
        printf("%d ",number[a]);
    }
    return 0;
 }

In this sample I planned it to give me error. Because I allocated it to size of 1 integer, then I wrote it way too much integers. Shouldn't it give me an error? Can you explain this with detail please?

struct people 
{
    char *name;
    int age;
    char *personalInfo;
} human[3];

When I define a structure like this, how can I allocate it to keep more than 3 human? How can I change it to something like human[20] or more? In case if the answer is writing *human instead of human[3], how should I allocate it? Like malloc(number*sizeof(char)*sizeof(int)*sizeof(char))?

And one more thing, in second example do I need to allocate name and personalInfo pointers?

Was it helpful?

Solution

In this sample i planned it to give me error.

You can't "plan to give an error". You're correct to say that the code is wrong because you are writing past the end of the array, but C has no bounds checking -- accessing the array is simply undefined behavior, which means that it can do literally anything -- it can pretend to work fine or it can crash, or it can cause demons to fly out of your nose.

How can i change it to something like human[20] or more?

Well... that's exactly how:

struct people {
   // members here
} human[20];

I don't see why the number "3" is so special. If you want to allocate memory dynamically, you would do it the way you would do in the case of every other data type: use the sizeof operator:

struct people *human = malloc(sizeof(human[0]) * number_of_people);

or

struct people *human = malloc(sizeof(struct people) * number_of_people);

OTHER TIPS

C does not provide compile-time or run-time bounds checking of arrays. The program must perform its own bound checking. If you write beyond the end of an array, your program will have undefined behavior. In practice it means that you're corrupting your process' memory by writing to uninitialized areas or areas that are used by allocators for bookkeeping. This can cause the program to crash immediately, crash on exit, or can overwrite the values of other (possibly unrelated) variables in the heap.

To allocate a variable number of people structures, you can do this:

struct people *humans;
humans = malloc(N * sizeof(struct people));
// humans now points to an array of N `people`

For your last question, yes, you must allocate space for those strings, unless you're simply using those pointers to point to strings defined/allocated elsewhere. Note this means that even in the code above where I allocate N objects, I still haven't allocated any space for the strings, and can't write to them until I do so.

struct people 
{
  char *name;
  int age;
  char *personalInfo;
};

struct people *human;

human = malloc(sizeof(*human) * 20);

In this sample i planned it to give me error. because i allocated it to size of 1 integer, then i wrote it way too much integers. Shouldn't it give me an error? Can you explain this with detail please?

No, it shouldn't. This is undefined behavior, which may lead to a crash at runtime, but the compiler will neither warn you about it nor produce any errors. You can detect errors like this by running your program in a memory profiler, such as valgrind.

When i define a structure like this, How can i allocate it to keep more than 3 human? How can i change it to something like human[20] or more?

Like this:

struct people *human = malloc(20 * sizeof(struct people));

Like malloc( number*sizeof(char)*sizeof(int)*sizeof(char) ) ?

Besides being too inconvenient, adding up sizes of individual fields may not produce the correct size, because the compiler is allowed to pad your struct to optimize access to its fields. That is why you need to use sizeof(struct people).

The first example invokes undefined behavior.

§6.5.6/8: If both the pointer operand and the result point to elements of the same array
 object, or one past the last element of the array object, the evaluation shall not 
produce an overflow; otherwise, the behavior is undefined

If you want to allocate for 20 humans, you can do...

typedef struct people 
{
    char *name;
    int age;
    char *personalInfo;
}People;

People *human;

human = malloc(sizeof(*human) * 20);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top