首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按照下面的代码示例,如何将作为指针函数的abc(x,y)存储到数组中?

问按照下面的代码示例,如何将作为指针函数的abc(x,y)存储到数组中?
EN

Stack Overflow用户
提问于 2021-07-10 13:25:59
回答 1查看 51关注 0票数 1
  • 函数1.
  • 是指针函数。

代码语言:javascript
复制
char *abc(unsigned int a, unsigned int b)
{
  //do something here ...
}

  • Function 2
  • 将函数1转化为函数2。
  • 我试图将abc函数存储到数组中,但我得到的错误为: error:类型.

。

代码语言:javascript
复制
fun2()
{
 unsigned int x, y;
  x= 5, y=6;
 char *array1;
 char array2;
 for(i=0; i<3; i++)
{
  array2[i] = abc(x, y);
}
}
EN

回答 1

Stack Overflow用户

发布于 2021-07-10 17:07:10

您不能将函数的调用存储在C中,因为它将挫败涉及寄存器参数传递的许多现有的流行优化--参见,因为通常在执行流转移到调用站点之前就会为参数分配参数值--编译器可以选择使用寄存器来存储这些值,但就目前情况而言,这些寄存器是不稳定的,因此,如果我们延迟实际调用,它们可能会在稍后的时间被覆盖--甚至可能是通过另一个调用将其参数作为寄存器传递给某个函数。一个解决方案--我亲自实现了--是让一个函数为您模拟调用,方法是向堆栈重新分配适当的寄存器和任何进一步的参数。在本例中,您将参数值存储在一个平面内存中。但是,这必须在专门用于此目的的程序集中完成,并且特定于您的目标体系结构。另一方面,如果您的体系结构没有使用任何这样的优化--这可能会非常容易,但仍然需要手工编写程序集。

在任何情况下,这都不是标准(甚至是我所知道的预标准)C在任何时候都没有实现的特性。

例如,这是我不久前编写的x86-64的实现(用于MSVC masm汇编程序):

代码语言:javascript
复制
PUBLIC makeuniquecall

.data

makeuniquecall_jmp_table    dq  zero_zero, one_zero, two_zero, three_zero ; ordinary

makeuniquecall_jmp_table_one    dq  zero_one, one_one, two_one, three_one ; single precision

makeuniquecall_jmp_table_two    dq  zero_two, one_two, two_two, three_two ; double precision

.code

makeuniquecall PROC
;rcx - function pointer
;rdx - raw argument data
;r8 - a byte array specifying each register parameter if it's float and the last qword is the size of the rest
push    r12
push    r13
push    r14

mov r12, rcx
mov r13, rdx
mov r14, r8

; first store the stack vars

mov rax, [r14 + 4] ; retrieve size of stack

sub rsp, rax

mov rdi, rsp
xor rdx, rdx
mov r8, 8
div r8
mov rcx, rax
mov rsi, r13
;add    rsi, 32

rep movs qword ptr [rdi], qword ptr [rsi]

xor r10,r10
cycle:
mov rax, r14
add rax, r10
movzx rax, byte ptr [rax]
test rax, rax
jnz jmp_one
lea rax, makeuniquecall_jmp_table
jmp qword ptr[rax + r10 * 8]
jmp_one:
cmp rax, 1
jnz jmp_two
lea rax, makeuniquecall_jmp_table_one
jmp qword ptr[rax + r10 * 8]
jmp_two:
lea rax, makeuniquecall_jmp_table_two
jmp qword ptr[rax + r10 * 8]

zero_zero::
mov rcx, qword ptr[r13+r10*8]
jmp continue
one_zero::
mov rdx, qword ptr[r13+r10*8]
jmp continue
two_zero::
mov r8, qword ptr[r13+r10*8]
jmp continue
three_zero::
mov r9, qword ptr[r13+r10*8]
jmp continue
zero_one::
movss xmm0, dword ptr[r13+r10*8]
jmp continue
one_one::
movss xmm1, dword ptr[r13+r10*8]
jmp continue
two_one::
movss xmm2, dword ptr[r13+r10*8]
jmp continue
three_one::
movss xmm3, dword ptr[r13+r10*8]
jmp continue
zero_two::
movsd xmm0, qword ptr[r13+r10*8]
jmp continue
one_two::
movsd xmm1, qword ptr[r13+r10*8]
jmp continue
two_two::
movsd xmm2, qword ptr[r13+r10*8]
jmp continue
three_two::
movsd xmm3, qword ptr[r13+r10*8]
continue:
inc r10
cmp r10, 4
jb  cycle

mov r14, [r14 + 4] ; retrieve size of stack

call    r12

add rsp, r14

pop r14
pop r13
pop r12

ret

makeuniquecall ENDP

END

您的代码将如下所示:

代码语言:javascript
复制
#include <stdio.h>

char* abc(unsigned int a, unsigned int b)
{
    printf("a - %d, b - %d\n", a, b);
    return "return abc str\n";
}

extern makeuniquecall();

main()
{
    unsigned int x, y;
    x = 5, y = 6;

#pragma pack(4)

    struct {
        struct { char maskargs[4]; unsigned long long szargs; } invok;
        char *(*pfunc)();
        unsigned long long args[2], shadow[2];
    } array2[3];

#pragma pack(pop)

    for (int i = 0; i < 3; i++)
    {
        memset(array2[i].invok.maskargs, 0, sizeof array2[i].invok.maskargs); // standard - no floats passed

        array2[i].invok.szargs = 8 * 4; //consider shadow space

        array2[i].pfunc = abc;

        array2[i].args[0] = x;
        array2[i].args[1] = y;
    }

    //now do the calls

    for (int i = 0; i < 3; i++)
        printf("%s\n", ((char *(*)())makeuniquecall)(array2[i].pfunc, array2[i].args, &array2[i].invok));
}

对于特定情况,您可能不需要这样做,只需存储每个参数并直接调用函数--也就是说(另外,这个方法不会是x86-64特定的):

代码语言:javascript
复制
//now do the calls

for (int i = 0; i < 3; i++)
    printf("%s\n", array2[i].pfunc(array2[i].args[0], array2[i].args[1]));

但是,我的实现为您提供了为每个调用存储不同数量的参数的灵活性。

注考虑在msvc上运行上述示例的this guide (因为它需要为程序集代码添加asm文件)。

我喜欢这样的问题,因为它们会让你思考为什么x-y特性实际上并不存在于语言中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68328147

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档