Skip to content

Instantly share code, notes, and snippets.

@haseeb-heaven
Last active January 4, 2025 12:04
Show Gist options
  • Save haseeb-heaven/22001f8609373ffe47be9dc0acbb5f30 to your computer and use it in GitHub Desktop.
Save haseeb-heaven/22001f8609373ffe47be9dc0acbb5f30 to your computer and use it in GitHub Desktop.
An innovative approach to returning values from void/null-based methods using function pointers, ensuring compatibility across all major operating systems.
#include <stdio.h>
#include <stdint.h>
// Define ARCH_NAME based on the detected architecture
#if defined(__x86_64__) || defined(_M_X64)
#define ARCH_NAME "x86_64"
#elif defined(__i386__) || defined(_M_IX86)
#define ARCH_NAME "x86"
#elif defined(__aarch64__) || defined(_M_ARM64)
#define ARCH_NAME "ARM64"
#else
#define ARCH_NAME "Unknown"
#endif
// Define get_factorial with a void return type
void get_factorial(int num) {
int64_t factorial = 1;
if (num < 0) {
factorial = -1;
} else {
for (int index = 1; index <= num; index++) {
factorial *= index;
}
}
// Inline assembly to move factorial into the appropriate return register
#if defined(__x86_64__) || defined(_M_X64)
// For x86_64 architecture (e.g., Windows, Linux, MacOS)
__asm__ __volatile__(
"mov %0, %%rax" // Move factorial into RAX (return register)
:
: "r" (factorial) // Input operand
: "rax" // Clobbered register
);
#elif defined(__i386__) || defined(_M_IX86)
// For x86 32-bit architecture (e.g., Windows, Linux, MacOS)
__asm__ __volatile__(
"mov %0, %%eax" // Move factorial into EAX (return register)
:
: "r" (factorial) // Input operand
: "eax" // Clobbered register
);
#elif defined(__aarch64__) || defined(_M_ARM64)
// For ARM64 architecture (e.g., MacOS ARM64, Linux ARM64)
__asm__ __volatile__(
"mov x0, %0" // Move factorial into X0 (return register)
:
: "r" (factorial) // Input operand
: "x0" // Clobbered register
);
#else
// Unsupported architecture: set factorial to -1
factorial = -1;
// No inline assembly for unsupported architectures
#endif
}
int main() {
int num = 5;
// Cast get_factorial to a function pointer that returns int64_t
int64_t (*func_ptr)(int) = (int64_t (*)(int))get_factorial;
int64_t factorial = func_ptr(num);
if (factorial == -1) {
// Print error with the detected architecture name
printf("Error: Unsupported architecture detected (%s).\n", ARCH_NAME);
} else {
printf("Factorial of %d: %lld\n", num, factorial);
}
return 0;
}
@haseeb-heaven
Copy link
Author

Better Approach by Claude.

#include <stdio.h>
#include <stdint.h>

void get_factorial(int64_t num) {
    int64_t factorial = 1;
    if (num < 0) {
        factorial = -1;
    } else {
        for (int index = 1; index <= num; index++) {
            factorial *= index;
        }
    }
    
    // Create a static variable to store the result
    static int64_t result;
    result = factorial;
    
    // Return the address of the static variable cast to void*
    return *(void**)&result;
}

int main() {
    int64_t num = 5;
    
    // Cast get_factorial to a function pointer that returns int64_t
    int64_t (*func_ptr)(int) = (int64_t (*)(int))get_factorial;
    int64_t factorial = func_ptr(num);
    
    if (factorial == -1) {
        printf("Error: Factorial of a negative number is undefined.\n");
    } else {
        printf("Factorial of %lld: %lld\n", num, factorial);
    }
    
    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment