C语言基础:形参与实参

    技术2026-02-02  4

    上课老师会给你讲函数的形参与实参的概念,前期基本上背诵,没有真正理解。这里写一个简单的例子说明下。

    测试用例如下: arm-linux-gcc test_para.c -o test_para 这里用交叉编译工具,方便后面读汇编代码

    测试结果,很明显real_swap_func才能达到交换的目的 简单的说你得往变量的地址写数据才能生效。形参只是往栈空间的某个地址写了一个数据,这个数据的值和入参的值相同,但是这个地址却不是形参本身的地址。

    先反汇编得到汇编代码: arm-linux-objdump -S test_para > test_para.txt 读汇编再来深入理解:

    00008490 <fake_swap_func>: 8490: e1a0c00d mov ip, sp 8494: e92dd800 stmdb sp!, {fp, ip, lr, pc} 8498: e24cb004 sub fp, ip, #4 ; 0x4 849c: e24dd00c sub sp, sp, #12 ; 0xc 84a0: e50b0010 str r0, [fp, #-16] 84a4: e50b1014 str r1, [fp, #-20] 84a8: e51b3010 ldr r3, [fp, #-16] 84ac: e50b3018 str r3, [fp, #-24] 84b0: e51b3014 ldr r3, [fp, #-20] 84b4: e50b3010 str r3, [fp, #-16] 84b8: e51b3018 ldr r3, [fp, #-24] 84bc: e50b3014 str r3, [fp, #-20] 84c0: e24bd00c sub sp, fp, #12 ; 0xc 84c4: e89da800 ldmia sp, {fp, sp, pc}

    000084c8 <real_swap_func>: 84c8: e1a0c00d mov ip, sp 84cc: e92dd800 stmdb sp!, {fp, ip, lr, pc} 84d0: e24cb004 sub fp, ip, #4 ; 0x4 84d4: e24dd00c sub sp, sp, #12 ; 0xc 84d8: e50b0010 str r0, [fp, #-16] 84dc: e50b1014 str r1, [fp, #-20] 84e0: e51b3010 ldr r3, [fp, #-16] 84e4: e5933000 ldr r3, [r3] 84e8: e50b3018 str r3, [fp, #-24] 84ec: e51b2010 ldr r2, [fp, #-16] 84f0: e51b3014 ldr r3, [fp, #-20] 84f4: e5933000 ldr r3, [r3] 84f8: e5823000 str r3, [r2] 84fc: e51b2014 ldr r2, [fp, #-20] 8500: e51b3018 ldr r3, [fp, #-24] 8504: e5823000 str r3, [r2] 8508: e24bd00c sub sp, fp, #12 ; 0xc 850c: e89da800 ldmia sp, {fp, sp, pc}

    00008510 : 8510: e1a0c00d mov ip, sp 8514: e92dd800 stmdb sp!, {fp, ip, lr, pc} 8518: e24cb004 sub fp, ip, #4 ; 0x4 851c: e24dd008 sub sp, sp, #8 ; 0x8 8520: e3a03003 mov r3, #3 ; 0x3 //往r3寄存器写0x3,也就是变量a的值 8524: e50b3010 str r3, [fp, #-16] //把r3的值写入fp-16的栈地址上 8528: e3a03005 mov r3, #5 ; 0x5 //往r3寄存器写0x5,也就是变量b的值 852c: e50b3014 str r3, [fp, #-20] //把r3的值写入fp-20的栈地址上 8530: e51b0010 ldr r0, [fp, #-16] //从fp-16的栈地址的值往r0寄存器写0x3,变量a的值 8534: e51b1014 ldr r1, [fp, #-20] //从fp-20的栈地址的值往r1寄存器写0x5,变量b的值 8538: ebffffd4 bl 8490 <fake_swap_func> //调用函数fake_swap_func,传参数r0, r1 ,了解arm传参机制 853c: e59f003c ldr r0, [pc, #60] ; 8580 <.text+0x1e4> 8540: e51b1010 ldr r1, [fp, #-16] 8544: e51b2014 ldr r2, [fp, #-20] 8548: ebffff90 bl 8390 <.text-0xc> 854c: e24b3010 sub r3, fp, #16 ; 0x10 //把fp-16的值(变量a的地址)写入r3寄存器,这里很重要 8550: e24b2014 sub r2, fp, #20 ; 0x14 //把fp-20的值(变量b的地址)写入r2寄存器,这里很重要 8554: e1a00003 mov r0, r3 //寄存器r3的值写入r0,这时候r0存的是变量a的地址 8558: e1a01002 mov r1, r2 //寄存器r2的值写入r1,这时候r1存的是变量 b的地址 855c: ebffffd9 bl 84c8 <real_swap_func> //调用函数fake_swap_func,传参数r0, r1 8560: e59f0018 ldr r0, [pc, #24] ; 8580 <.text+0x1e4> 8564: e51b1010 ldr r1, [fp, #-16] 8568: e51b2014 ldr r2, [fp, #-20] 856c: ebffff87 bl 8390 <.text-0xc> 8570: e3a03000 mov r3, #0 ; 0x0 8574: e1a00003 mov r0, r3 8578: e24bd00c sub sp, fp, #12 ; 0xc 857c: e89da800 ldmia sp, {fp, sp, pc} 8580: 00008698 muleq r0, r8, r6

    ps:8510 是main函数的地址,不知道为何不能显示

    末尾再写句废话:真正想了解C语言,汇编是无法逃避的

    Processed: 0.021, SQL: 9