在 C 中使用省略号传递参数 [英] Parameter passing with ellipsis in C

查看:80
本文介绍了在 C 中使用省略号传递参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在 C 中实现我自己的 printf 函数.但是我在将省略号 ("...") 功能与我的函数一起使用时遇到了问题(我们需要使用省略号).

I need to implement my own printf function in C. However I am having trouble using the ellipsis ("...") feature with my function (we are required to use ellipsis).

根据我的教科书,传递给带有省略号的函数的参数应该位于存储第一个参数的堆栈正上方.但是,我在堆栈上的任何地方都找不到我传递的任何附加参数!这是我用来测试我的函数和输出的一些代码:

According to my textbook, the parameters passed to a function with an ellipsis should be located on the stack right above where the first parameter is stored. I can not find any of the the additional parameters I am passing anywhere on the stack though! Here is some code I used to test my function and the output:

#include<stdio.h>
#include<stdlib.h>

int myprintf(char *str, ...)
{
    //test code to view data around str on the stack:
    int i;
    for (i = -8; i <= 8; i++)
    {
        char *ptr = str + (i * 4); // ptr will iterate through the 8 bytes above and
                                   // below str[0] on the stack
        printf ("Bytes from str: %+03d \t
                 Ptr Addr: %x \t
                 Val int: %d \t
                 Val char: %c \n",
                 (i*4), ptr, *ptr, *ptr);
    }

    //my implementation of printf...
}

int main(void)
{
    myprintf("test string", 1111, 2222, 3333);
}

这是 myprintf 函数的输出(堆栈的打印输出):

Here is the output of the myprintf function (a printout of the stack):

Bytes from str: -32    Ptr Addr: 8048922    Val int:         48    Val char: 0
Bytes from str: -28    Ptr Addr: 8048926    Val int:         97    Val char: a
Bytes from str: -24    Ptr Addr: 804892a    Val int:        104    Val char: h
Bytes from str: -20    Ptr Addr: 804892e    Val int:         32    Val char:  
Bytes from str: -16    Ptr Addr: 8048932    Val int:          0    Val char: 
Bytes from str: -12    Ptr Addr: 8048936    Val int:        118    Val char: v
Bytes from str: -08    Ptr Addr: 804893a    Val int:         93    Val char: ]
Bytes from str: -04    Ptr Addr: 804893e    Val int:         37    Val char: % <- my other variables should be here and above
Bytes from str: +00    Ptr Addr: 8048942    Val int:        116    Val char: t <-"test string"
Bytes from str: +04    Ptr Addr: 8048946    Val int:         32    Val char:   <-" string"
Bytes from str: +08    Ptr Addr: 804894a    Val int:        105    Val char: i <-"ing"
Bytes from str: +12    Ptr Addr: 804894e    Val int:          0    Val char: 
Bytes from str: +16    Ptr Addr: 8048952    Val int:          3    Val char: 
Bytes from str: +20    Ptr Addr: 8048956    Val int:          0    Val char: 
Bytes from str: +24    Ptr Addr: 804895a    Val int:          0    Val char: 
Bytes from str: +28    Ptr Addr: 804895e    Val int:         -1    Val char: �
Bytes from str: +32    Ptr Addr: 8048962    Val int:          0    Val char:

据我所知,值 1111、2222 和 3333 应该位于此堆栈打印输出中的某个位置.当我进行函数调用时,这些值会去哪里?

From what I understand, the values 1111, 2222, and 3333 should be located somewhere in this stack printout. Where are these values going when I make the function call?

我无法在我的实现中使用stdarg.h"库.

I cannot use the "stdarg.h" library in my implementation.

推荐答案

这个程序的行为可能不被规范所允许,但是对于这个从堆栈中搜索参数的实验,你必须移动指针指向 参数而不是指针 作为 参数传递.

Behavior of this program may not granteed by the specification, but for this experiment of searching argument from the stack, you have to move the pointer pointing at the argument instead of the pointer passed as the argument.

#include<stdio.h>
#include<stdlib.h>

int myprintf(char *str, ...)
{
    //test code to view data around str on the stack:
    int i;
    for (i = -8; i <= 8; i++)
    {
        /* add & before str to get the address of the argument */
        char *ptr = (char*)&str + (i * 4); // ptr will iterate through the 4 * 8 bytes above and
                                   // below str on the stack
        printf ("Bytes from str: %+03d \t"
                 "Ptr Addr: %p \t"
                 "Val int: %d \t"
                 "Val char: %02X \n",
                 (i*4), (void*)ptr, *(int*)ptr, (unsigned int)(unsigned char)*ptr);
    }

    //my implementation of printf...
    return 0;
}

int main(void)
{
    myprintf("test string", 1111, 2222, 3333);
    return 0;
}

在我的本地环境中的结果:

Result in my local environment:

Bytes from str: -32     Ptr Addr: 0028FF10  Val int: 213    Val char: D5 
Bytes from str: -28     Ptr Addr: 0028FF14  Val int: 1662423109     Val char: 45 
Bytes from str: -24     Ptr Addr: 0028FF18  Val int: -2     Val char: FE 
Bytes from str: -20     Ptr Addr: 0028FF1C  Val int: 1972834658     Val char: 62 
Bytes from str: -16     Ptr Addr: 0028FF20  Val int: 2130567168     Val char: 00 
Bytes from str: -12     Ptr Addr: 0028FF24  Val int: 0  Val char: 00 
Bytes from str: -08     Ptr Addr: 0028FF28  Val int: 0  Val char: 00 
Bytes from str: -04     Ptr Addr: 0028FF2C  Val int: 4227938    Val char: 62 
Bytes from str: +00     Ptr Addr: 0028FF30  Val int: 4235431    Val char: A7 
Bytes from str: +04     Ptr Addr: 0028FF34  Val int: 1111   Val char: 57 
Bytes from str: +08     Ptr Addr: 0028FF38  Val int: 2222   Val char: AE 
Bytes from str: +12     Ptr Addr: 0028FF3C  Val int: 3333   Val char: 05 
Bytes from str: +16     Ptr Addr: 0028FF40  Val int: 0  Val char: 00 
Bytes from str: +20     Ptr Addr: 0028FF44  Val int: 0  Val char: 00 
Bytes from str: +24     Ptr Addr: 0028FF48  Val int: 2686824    Val char: 68 
Bytes from str: +28     Ptr Addr: 0028FF4C  Val int: 4198992    Val char: 50 
Bytes from str: +32     Ptr Addr: 0028FF50  Val int: 1  Val char: 01 

正如@Joe 所说,使用 va_* 宏来读取可变数字参数.否则,该程序可能无法在某些环境中运行——例如,x86_64,其中参数在寄存器上传递,而不是在堆栈上.

As @Joe says, use va_* macro to read variable number arguments. Otherwise, the program may not work in some environment -- for example, x86_64 where arguments are passed on register, not on the stack.

我做了一些修改

  • 扩大搜索范围
  • 打印传递的字符串地址

并在 Wandbox 上运行代码.

and ran the code on Wandbox.

结果变成了这样:

Bytes from str: -64     Ptr Addr: 0x7fff2308b498    Val int: -1473084125    Val char: 23 
Bytes from str: -60     Ptr Addr: 0x7fff2308b49c    Val int: 0  Val char: 00 
Bytes from str: -56     Ptr Addr: 0x7fff2308b4a0    Val int: 4196088    Val char: F8 
Bytes from str: -52     Ptr Addr: 0x7fff2308b4a4    Val int: 0  Val char: 00 
Bytes from str: -48     Ptr Addr: 0x7fff2308b4a8    Val int: 35     Val char: 23 
Bytes from str: -44     Ptr Addr: 0x7fff2308b4ac    Val int: 0  Val char: 00 
Bytes from str: -40     Ptr Addr: 0x7fff2308b4b0    Val int: -1473063104    Val char: 40 
Bytes from str: -36     Ptr Addr: 0x7fff2308b4b4    Val int: 32682  Val char: AA 
Bytes from str: -32     Ptr Addr: 0x7fff2308b4b8    Val int: -1470881080    Val char: C8 
Bytes from str: -28     Ptr Addr: 0x7fff2308b4bc    Val int: 32682  Val char: AA 
Bytes from str: -24     Ptr Addr: 0x7fff2308b4c0    Val int: 0  Val char: 00 
Bytes from str: -20     Ptr Addr: 0x7fff2308b4c4    Val int: 0  Val char: 00 
Bytes from str: -16     Ptr Addr: 0x7fff2308b4c8    Val int: 4195810    Val char: E2 
Bytes from str: -12     Ptr Addr: 0x7fff2308b4cc    Val int: 0  Val char: 00 
Bytes from str: -08     Ptr Addr: 0x7fff2308b4d0    Val int: 0  Val char: 00 
Bytes from str: -04     Ptr Addr: 0x7fff2308b4d4    Val int: 0  Val char: 00 
Bytes from str: +00     Ptr Addr: 0x7fff2308b4d8    Val int: 4196155    Val char: 3B 
Bytes from str: +04     Ptr Addr: 0x7fff2308b4dc    Val int: 0  Val char: 00 
Bytes from str: +08     Ptr Addr: 0x7fff2308b4e0    Val int: 587773152  Val char: E0 
Bytes from str: +12     Ptr Addr: 0x7fff2308b4e4    Val int: 32767  Val char: FF 
Bytes from str: +16     Ptr Addr: 0x7fff2308b4e8    Val int: -1477724000    Val char: A0 
Bytes from str: +20     Ptr Addr: 0x7fff2308b4ec    Val int: 5  Val char: 05 
Bytes from str: +24     Ptr Addr: 0x7fff2308b4f0    Val int: -1475311104    Val char: 00 
Bytes from str: +28     Ptr Addr: 0x7fff2308b4f4    Val int: 32682  Val char: AA 
Bytes from str: +32     Ptr Addr: 0x7fff2308b4f8    Val int: 1111   Val char: 57 
Bytes from str: +36     Ptr Addr: 0x7fff2308b4fc    Val int: 0  Val char: 00 
Bytes from str: +40     Ptr Addr: 0x7fff2308b500    Val int: 2222   Val char: AE 
Bytes from str: +44     Ptr Addr: 0x7fff2308b504    Val int: 0  Val char: 00 
Bytes from str: +48     Ptr Addr: 0x7fff2308b508    Val int: 3333   Val char: 05 
Bytes from str: +52     Ptr Addr: 0x7fff2308b50c    Val int: 0  Val char: 00 
Bytes from str: +56     Ptr Addr: 0x7fff2308b510    Val int: 4196064    Val char: E0 
Bytes from str: +60     Ptr Addr: 0x7fff2308b514    Val int: 0  Val char: 00 
Bytes from str: +64     Ptr Addr: 0x7fff2308b518    Val int: -1473063104    Val char: 40 
pointer passed = 4196155 0x40073b

如您所见,值作为 Bytes from str: +00 上的指针传递,但其他参数的值不接近该值.

As you see, the valued passed as pointer on Bytes from str: +00, but value of the other arguments are not near the value.

这篇关于在 C 中使用省略号传递参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆