0

Can a function tell what's calling it, through the use of memory addresses maybe? For example, function foo(); gets data on whether it is being called in main(); rather than some other function?

If so, is it possible to change the content of foo(); based on what is calling it? Example:

int foo()
{
 if (being called from main())
    printf("Hello\n");
 if (being called from some other function)
    printf("Goodbye\n");
}

This question might be kind of out there, but is there some sort of C trickery that can make this possible?

user12787203
  • 103
  • 6
  • 1
    Not in standard C, no. There could be a platform-specific solution, but I can't imagine it being reliable. [What problem are you trying to solve?](https://meta.stackexchange.com/q/66377/353058) – HolyBlackCat Jun 08 '21 at 06:40
  • 3
    Sounds like an [XY Problem](https://en.wikipedia.org/wiki/XY_problem) to me. – Devolus Jun 08 '21 at 06:43
  • 2
    A function should not depend on the calling site; that would be very weird. At least explain why you want such... – Jean-Baptiste Yunès Jun 08 '21 at 06:45
  • 1
    If this is a practical question, one potential alternative would be: pass in an enum value to `foo` with the "context" relative to where it's being called. – MrHappyAsthma Jun 08 '21 at 06:47
  • You can invent something like a "manual call stack" with a list of function pointers that you pass around. Cumbersome and probably not very useful. – Lundin Jun 08 '21 at 08:41

5 Answers5

2

For highly optimized C it doesn't really make sense. The harder the compiler tries to optimize the less the final executable resembles the source code (especially for link-time code generation where the old "separate compilation units" problem no longer prevents lots of optimizations). At least in theory (but often in practice for some compilers) functions that existed in the source code may not exist in the final executable (e.g. may have been inlined into their caller); functions that didn't exist in the source code may be generated (e.g. compiler detects common sequences in many functions and "out-lines" them into a new function to avoid code duplication); and functions may be replaced by data (e.g. an "int abcd(uint8_t a, uint8_t b)" replaced by a abcd_table[a][b] lookup table).

For strict C (no extensions or hacks), no. It simply can't support anything like this because it can't expect that (for any compiler including future compilers that don't exist yet) the final output/executable resembles the source code.

An implementation defined extension, or even just a hack involving inline assembly, may be "technically possible" (especially if the compiler doesn't optimize the code well). The most likely approach would be to (ab)use debugging information to determine the caller from "what the function should return to when it returns".

A better way for a compiler to support a hypothetical extension like this may be for the compiler to use some of the optimizations I mentioned - specifically, split the original foo() into 2 separate versions where one version is only ever called from main() and the other version is used for other callers. This has the bonus of letting the compiler optimize out the branches too - it could become like int foo_when_called_from_main() { printf("Hello\n"); }, which could be inlined directly into the caller, so that neither version of foo exists in the final executable. Of course if foo() had other code that's used by all callers then that common code could be lifted out into a new function rather than duplicating it (e.g. so it might become like int foo_when_called_from_main() { printf("Hello\n"); foo_common_code(); }).

There probably isn't any hypothetical compiler that works like that, but there's no real reason you can't do these same optimizations yourself (and have it work on all compilers).

Note: Yes, this was just a crafty way of suggesting that you can/should refactor the code so that it doesn't need to know which function is calling it.

Brendan
  • 35,656
  • 2
  • 39
  • 66
1

Knowing who called a specific function is essentially what a stack trace is visualizing. There are no general standard way of extracting that though. In theory one could write code that targeted each system type the software would run on, and implement a stack trace function for each of them. In that case you could examine the stack and see what is before the current function.

But with all that said and done, the question you should probably ask is why? Writing a function that functions in a specific way when called from a specific function is not well isolated logic. Instead you could consider passing in a parameter to the function that caused the change in logic. That would also make the result more testable and reliable.

How to actually extract a stack trace has already received many answers here: How can one grab a stack trace in C?

Tommy Andersen
  • 7,165
  • 1
  • 31
  • 50
  • Just curiosity, I'm not planning on implementing anything like this. Im working on a project where the function parameters can't be changed. – user12787203 Jun 08 '21 at 06:47
  • You might consider this answer of interest: https://stackoverflow.com/questions/105659/how-can-one-grab-a-stack-trace-in-c – Tommy Andersen Jun 08 '21 at 06:48
0

I think if loop in C cannot have a condition as you have mentioned. If you want to check whether this function is called from main(), you have to do the printf statement in the main() and also at the other function.

Assaulter_OO7
  • 11
  • 2
  • 5
0

I don't really know what you are trying to achieve but according to what I understood, what you can do is each function will pass an additional argument that would uniquely identify that function in form of a character array, integer or enumeration. for example:

enum function{main, add, sub, div, mul};

and call functions like:

add(3,5,main);//adds 3 and 5. called from main

changes to the code would be typical like if you are adding more functions. but it's an easier way to do it.

0

No. The C language does not support obtaining the name or other information of who called a function.

As all other answers show, this can only be obtained using external tools, for example that use stack traces and compiler/linker emitted symbol tables.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41