为什么它可以在Windows中工作但不能在Linux中工作?

时间:2019-11-10 06:26:32

标签: c linux

我的代码如下。

当我使用Visual Studio进行编译,调试和执行时,这是正确的。当我使用'gcc'进行编译时,这也是正确的,但是在Linux中执行时是错误的。运行时内存错误。

当打印'szBuf'时,错误是无法访问内存。

我想知道为什么在Windows中可以使用,但在Linux中不能使用?

#include <stdio.h>

void ItoA(int nNum, char *pStr);
void Print(const char *pFormat, ...);

int main()
{
    char  ch = 'a';
    int nNum = 11;
    char szBuf[255] = "";

    Print("ch: %c\n", ch);
    Print("n: %d\n", nNum);
    Print("s: %s\n", szBuf);

    return 0;
}

void ItoA(int nNum, char *pStr)
{
    if (NULL != pStr)
    {
        char szNum[255] = "";
        int i = 0;

        for (i = 0; 0 != nNum; i++)
        {
            szNum[i] = nNum % 10 + '0';
            nNum /= 10;
        }

        for (i = i - 1; i >= 0; i--, pStr++)
        {
            *pStr = szNum[i];
        }
        *pStr = '\0';
    }
}

void Print(const char *pFormat, ...)
{
    if (NULL != pFormat)
    {
        char *pTemp = (char *)&pFormat;
        pTemp += 4;

        while ('\0' != *pFormat)
        {
            if ('%' == *pFormat)
            {
                pFormat++;
                switch (*pFormat)
                {
                case 'c':
                {
                    putchar(*pTemp);
                    pTemp += 4;
                }
                break;
                case 'd':
                {
                    char szBuf[255] = "";
                    int nNum = 0;

                    ItoA(*(int *)pTemp, szBuf);

                    for (int i = 0; '\0' != szBuf[i]; i++)
                    {
                        putchar(szBuf[i]);
                    }

                    pTemp += 4;
                }
                break;
                case 's':
                {
                    for (int i = 0; '\0' != (*(char **)pTemp)[i]; i++)
                    {
                        putchar((*(char **)pTemp)[i]);
                    }

                    pTemp += 4;
                }
                break;
                default:
                {
                    pFormat--;
                    putchar(*pTemp);
                }
                break;
                }
            }
            else
            {
                putchar(*pFormat);
            }
            pFormat++;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

这些行以及pTemp周围的所有内容都有未定义的行为:

    char *pTemp = (char *)&pFormat;
    pTemp += 4;

您必须使用va_start中的va_argstdarg.h来获得可变参数。 &pFormatPrint函数中局部变量的地址,与参数的传递方式无关。指向一个对象的指针的算术运算不能产生指向另一个对象的指针。

答案 1 :(得分:0)

虽然某些调用约定使用堆栈传递函数参数, 有些呼叫转化使用注册传递。

您的代码可以用于使用堆栈的调用约定,但不能用于使用寄存器的调用约定< / strong>。

看来,Visual Studio的默认值为x86编译(32位,通常使用堆栈),而gcc的默认值为64位编译(通常使用寄存器)。 >

您应该使用stdarg.h中的API从变量参数列表中获取值。