-1
int *tomato(int *a, int *b) {
    int *foo = (int*)malloc(sizeof(int));
    *foo = *a + *b;
    return foo;
}

In this function I have foo that is allocated in heap and returns a pointer to int, but are the pointers *a and *b in the function arguments also allocated in heap? I am a bit confused here, generally, arguments are allocated in stack.

trincot
  • 317,000
  • 35
  • 244
  • 286
nihulus
  • 1,475
  • 4
  • 24
  • 46
  • 3
    They can be allocated anywhere. The caller decides where they're located. – Barmar Apr 24 '19 at 21:34
  • 1
    [don't cast malloc](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Barmar Apr 24 '19 at 21:34
  • 1
    "*arguments are allocated in stack*" - not necessarily. The language does not specify, and in many calling conventions, at least some arguments are passed in registers rather than on the stack. But that's anyway about the location of the *pointers* `a` and `b`, not about the data to which they point. – John Bollinger Apr 24 '19 at 21:37

2 Answers2

3

The pointers are local variables in the tomato function, just like foo.

The values that they point to can be allocated anywhere. For instance, you can call it like this:

int foo = 1;
int *bar = malloc(sizeof(int));
*bar = 3;
int *result = tomato(&foo, bar);

a will point to a the foo variable, while b will point to the memory allocated by malloc.

Barmar
  • 741,623
  • 53
  • 500
  • 612
1

Parameters in C are not necessarily allocated in the stack (*), but their scope will necessarily be restricted to the tomato function block, and they will necessarily be passed by value.

When you dereference a and b in the assignment *foo = *a + *b, you are interpreting the memory address stored in pointers a and b as integers, summing them, and writing the result in the memory address stored in pointer foo (which, in your example, happens to be in the heap).

After the assignment, you could change a and b at will by assigning different memory addresses to them (i.e. pointers), and there would be no consequence to any external memory references as their scope is limited to the function block (e.g. a = foo). If, however, you changed the memory contents referred by them (e.g. *a = 0), this would become visible outside the scope of the function as you would be writing on a memory space (stack or heap) allocated somewhere else.

(*) Parameters may not be passed in memory (i.e. stack) to functions. Depending on the compiler/architecture, they may be directly assigned to a processor register. Either way, this is a transparent compiler optimization and you don't have to worry about it... the parameters will behave just the same.