-22

Can't you just store as much data as you want using pointer? Why do you have to use malloc() to gain more memory?

int * a;
int max, i;
printf("Enter the maximum number you want: ");
scanf("%d", &max);

for (i = 0; i < max; i++)
{
    * (a + i) = i;
}

for (i = 0; i < max; i++)
{
    printf("%d\n", * (a + i));
}
return 0;

so I let the user choose whatever number, and computer will 'allocate the memory' right? instead of using the following code:

a = (int *) malloc(10 * sizeof(int));
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Jin kim
  • 155
  • 1
  • 2
  • 8
  • 1
    to gain more memory you use realloc – maraca Jul 16 '15 at 09:45
  • @maraca: That wouldn't work here, as realloc requires an initialized pointer to start with. – MSalters Jul 16 '15 at 09:46
  • 1
    You are overwriting random memory areas that you did not reserved: not only you can corrupt data but also you have no guarantee that you will be able to retrieve the data you wrote. More likely you will end up in a segfault because this is undefined behavior. – n0p Jul 16 '15 at 09:46
  • @MSalters yes... my point is to gain more you have to have something first... so malloc is not to gain more, it is realloc, but malloc should be used first. – maraca Jul 16 '15 at 09:47
  • 1
    @Jin kim It is a splendid idea! I like it. Let the compiler bothers about allocating memory somewhere where it likes.:) – Vlad from Moscow Jul 16 '15 at 09:49
  • @Jin kim Your program would look even better if you add one minor detail including a word in the print statement. For example printf("Enter the maximum number of money you want: "); – Vlad from Moscow Jul 16 '15 at 09:53
  • 2
    @MSalters False. `realloc`, when passed a `NULL` pointer, behaves like `malloc`. – fuz Jul 16 '15 at 09:53
  • @VladfromMoscow: But that would change the meaning, maybe he wants to know what is the maximum number you want to have, maybe its a "Count von Count" emulator?:D – dhein Jul 16 '15 at 09:55
  • 2
    @FUZxxl: `NULL` is a value. Uninitialized pointers aren't NULL and NULL pointers are initialized. E.g. MSVC++ will set uninitialized pointers to `0xcdcdcdcd` in debug mode so you can spot the bug. – MSalters Jul 16 '15 at 10:58

3 Answers3

7

In your code,

  * (a + i) = i;

is wrong, because you're trying to write into uninitialized memory. This in turn invokes undefined behaviour.

To elaborate, just defining a pointer does not automatically allocate limitless accessible memory to that pointer. You need to add the location where the pointer will be pointing to. When you simply define a pointer (local), it points to some unknown memory location which is most likely neither valid nor accessible by your program. So, when you try to access that memory location, it is essentially accessing some invalid memory. This is UB.

So,

Why do you have to use malloc to gain more memory?

malloc() is not used to gain more memory, rather it is giving the required memory location to be accessed.


EDIT:

Regarding your edit,

 a = (int *) malloc(10 * sizeof(int));

two things to add,

  1. Please see why not to cast the return value of malloc() and family in C.
  2. Always check for the success of malloc() before using the returned pointer.
Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • I am using it like array. a[10] would be the same as * a if i put in 10 values in it. right? and the code works. you can initialize it during the program not just at the top of main. – Jin kim Jul 16 '15 at 10:07
  • 1
    @Jinkim To be truthful, arrays can be represented using pointers but they are very different. Maybe the [C-FAQ](http://c-faq.com/aryptr/index.html) will help you clear the understanding. – Sourav Ghosh Jul 16 '15 at 10:10
  • @Jinkim In case of a normal array, memory allocation is handled by the compiler, so it will always have a valid memory when accessed within the bounds, but for pointers, you need to allocate memory, either by dynamic allocation, or pointing that pointer to the address of some normal variable of that type. – Sourav Ghosh Jul 16 '15 at 10:12
1

A pointer has to point to some location in memory, so never write

int* x;
*x=...;

But write

int* x=expression that results in an valid address;

First consider a simple computer without MMU and a fancy multitasking OS. Then you can use any address, but you have to know you do not replace your code, and any important data. You will benefit from having a reserved space for code, the call stack and perhaps other data. Some machines connects addresses to peripherals, so writing there would make some physical stuff happen. This is called memory mapped I/O. To know what you are doing, you create your address layout, which on a 16 bit machine may look like

+------------------+ 0x0000
| Memory mapped IO |
+------------------+ 0x0100
| Program          |
|                  |
+------------------+ 0x4000
| Call stack       |
| (local variables)|
+------------------+ 0x8000
| Other data       |
| globals          |
| heap             |
+------------------+ 0xffff

This fictive machine has 255 I/O ports (0x0000 is reserved), and will start program on address 0x0100. The remaining part of the address layout is up to you. Here 16128 bytes is reserved for the program , 16384 bytes for the stack and 32767 bytes left for other data. If you know that your program never becomes larger than 8 kB, then feel free to increase your call stack or heap. A program that sets the rotation speed of a motor may look like

int main()
    {
    const uint8_t* speed_regulator=(const uint8_t*)0x0001; //Port for speed controller is 0x0000
    uint8_t* motor_voltage=(uint8_t*)0x0002; //Port for motor controller

    while(true)
        {
        *motor_voltage=*speed_regulator;
        }
    }

Some care must be taken here, so the compiler does not optimise out the loop, which is our data pump.

Now you want a multitasking system with virtual memory and all modern stuff. But then you cannot use arbitrary addresses any more. To make it possible to give you a valid address, and to inform the OS about how much memory you need, the function malloc exists.

user877329
  • 6,717
  • 8
  • 46
  • 88
1

so I let the user choose whatever number, and computer will 'allocate the memory' right?

Some languages work like that; the runtime environment will allocate memory from the heap (or whatever memory pool) as necessary.

C does not work that way. When you declare

int *a;

a doesn't initially point anywhere meaningful; if declared static or at file scope it initially contains NULL, and if declared within a block it contains an indeterminate value which may or may not point to a writable memory location. It does not automatically point to the heap, and writing *(a + i) = i (or a[i] = i, which is the same thing) won't automatically allocate any new memory.

C puts all the burden on the programmer for managing dynamically allocated memory. If you need additional memory at runtime, you must use malloc or realloc, and when you're done with that memory, you must deallocate it using free.

John Bode
  • 119,563
  • 19
  • 122
  • 198