为什么这个输出看起来不确定?(它是sprintf,printf还是十六进制文字的语法?)

And*_*ong 2 c++ debugging printf hex

TL;博士

为什么每次运行此代码时都会得到不同的输出(Ideone):

#include <iostream>
#include <stdio.h>
using namespace std;

int main() {

    const char* _user = "FOO";
    const char* _password = "BAR";

    char login[21];
    sprintf(login,
        "\x15\x00\x01%-8s%-10s",
        _user,
        _password);

    for (int i = 0; i < 21; i++) {
        printf(" %02x", login[i] & 0xff);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但不是这个代码(Ideone):

#include <iostream>
#include <stdio.h>
using namespace std;

int main() {

    const char* _user = "FOO";
    const char* _password = "BAR";
    const char* _session = "ABCDEFGHIJ";
    int _expectedSeq = 123;

    char login[38];
    sprintf(login,
            "L%-6s%-10s%10s%10d\xA",
            _user,
            _password,
            _session,
            _expectedSeq);

    for (int i = 0; i < 38; i++) {
        printf(" %02x", login[i] & 0xff);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在我们的应用程序代码深处,我遇到了这个:

char login[38];
sprintf(login,
        "L%-6s%-10s%10s%10d\xA",
        _user,
        _password,
        _session,
        _expectedSeq);
Run Code Online (Sandbox Code Playgroud)

现在,我需要编写一个(更简单的)此代码的变体:

char login[21];
sprintf(login,
       "\x15\x00\x01%-8s%-10s",
       _user,
       _password);
Run Code Online (Sandbox Code Playgroud)

不知何故,这不起作用!奇怪的是,后者每次都会产生不同的结果.


思考

  1. 前一个示例最后只有一个十六进制文字.这是否掩盖了前者的问题?

  2. 或者,我实际上搞砸了我的调试输出,printf?(顺便说一下,我& 0xffC中打印十六进制字符得到了东西.)

  3. 它可能与使用char而不是unsigned char?但是,为什么前一种情况有效呢?

rod*_*igo 6

问题是你的字符串文字有一个嵌入的NUL字节,并且标志着字符串的结尾sprintf.所以你的电话是这样的:

sprintf(login,
       "\x15",
       _user,
       _password);
Run Code Online (Sandbox Code Playgroud)

并且login只在两个字节中写入数组:0x15 0x00.

有几种方法可以解决字节和字符的混合问题.我的选择将是:

memcpy(login, "\x15\x00\x01", 3);
sprintf(login + 3,
   "%-8s%-10s",
   _user,
   _password);    
Run Code Online (Sandbox Code Playgroud)

调用memcpy将参数作为参数的字节数,因此它不受嵌入式NUL问题的影响.

但请注意,sprintfautomaticall在输出字符串的末尾添加一个NUL字节,因此实际上需要22个字节:3 + 8 + 10 + 1 = 22:

char login[22];
Run Code Online (Sandbox Code Playgroud)