【问题标题】:own printf function does not work [closed]自己的 printf 功能不起作用[关闭]
【发布时间】:2014-11-19 04:58:14
【问题描述】:

我正在尝试用 c++ 编写自己的 printf func 以进行实践,但出现以下运行时错误,我不知道为什么:

Access violation reading location 0x33333333.

代码如下:

void myPrintf(char* szStr, ...)
{
    va_list marker;
    va_start(marker, szStr);
    va_arg(marker, char*);
    char opCode;
    int nLen = istrlen(szStr);
    for (int i = 0; i < nLen; i++)
    {
        if (szStr[i] != '%')
            cout << szStr[i];
        else
        {
            if (i + 1 < nLen)
            {
                opCode = szStr[i + 1];
                switch (opCode)
                {
                case 'd':
                    cout << va_arg(marker, int);
                    i += 2;
                    break;
                case 'f':
                    cout << va_arg(marker, float);
                    i += 2;
                    break;
                case 's':
                    cout << va_arg(marker, char*);
                    i += 2;
                    break;
                default:
                    cout << '%';
                    break;
                }
            }
            else
                cout << '%';
        }
    }
    cout << endl;
}

我不明白为什么会这样, 有人可以告诉我我做错了什么吗?

我正在使用以下代码调用该函数:

myPrintf("%d %s %f", 5, "test", 10.1);

当程序崩溃时,它向我展示了这段代码:

static size_t __CLRCALL_OR_CDECL length(const _Elem *_First)
    {   // find length of null-terminated string
    return (*_First == 0 ? 0
        : _CSTD strlen(_First));
    }

【问题讨论】:

  • 那么在你的调试器中,它在哪里崩溃了?你用什么代码调用你的函数?
  • 是的,但它在哪里崩溃?使用调试器逐步完成。
  • 看起来您需要检查指针是否为 NULL。
  • 如果无法使用调试器,请使用std::cerr从关键位置向控制台写入一些消息,以找出错误发生的位置。
  • 我不确定我使用的是 Visual Studio,当它崩溃时显示变量 _First(来自我展示的函数)设置为 0x33333333

标签: c++ arguments variadic-functions


【解决方案1】:

va_start(marker, szStr); 之后的第一个 va_arg(marker, char*); 可能应该被删除,因为它使用了szStr 之后的参数(即您示例中的 5)。 va_start 宏正在使用起始参数。

并且float 参数总是作为double 传递(同样short 参数作为int 传递等等...)所以你的va_arg(marker, float); 应该是va_arg(marker, double);

【讨论】:

  • 它不消耗字符串本身吗? “%d %s %f”?
  • 没有。 va_start() 将marker 设置为指向szStr 之后的第一个参数。每次调用va_arg() 时,它会将marker 前进到下一个参数并返回一个指向marker 先前指向的位置的指针。因此,第一个va_arg(char*) 正在使用5 参数,因此当"%d" 被解析时,va_arg(int) 将返回"Test" 参数,然后当"%s" 被解析时,va_arg(char*) 将返回@ 987654346@参数等。
  • 我认为它消耗了第一个参数,我的错,我也将 i+=2 更改为 i++ 因为我忘记了它每次迭代都会添加到 i 中,除了浮点数被打印为某些东西外,一切正常否则,在我的情况下,10.1 被打印为 4.17233e-008
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-29
相关资源
最近更新 更多