sprintf - 它实际上做了什么

时间:2014-06-04 08:43:22

标签: c printf

这是我的代码的一部分

int pic_num = 1;
printf("pic_num = %i\n", pic_num);
sprintf(picture, "%03d.jpg", pic_num);
printf("%s, pic_num = %i\n", picture, pic_num);'

pic_num的第一个值是1,但是第二个值,在sprintf之后是6778986 为什么? sprintf实际上做了什么?我以为它只是制作一个字符串图片= 001.jpg 但是pic_num怎么样?为什么会改变一个值?

谢谢

你们都是怀疑的。它应该是[8]或[16]。谢谢大家。

3 个答案:

答案 0 :(得分:9)

6778986以十六进制给出0x0067706A,它对应于"jpg"中应该包含的最后3个ASCII字符和空终止符(picture)字符串。

这表示您在picture之前定义了pic_num,并且只有4个字节。我猜你把它定义为:

char picture[4];

您需要正确调整字符串的大小,以保留至少8个字符(但可能更多取决于pic_num值可以获得的大小),因此sprintf写入的字符串不会包含#39} ; t溢出到pic_num。例如:

char picture[16];

有关sprintf的更多信息,请参阅此参考资料,例如。 :http://en.cppreference.com/w/c/io/fprintf

答案 1 :(得分:3)

sprintf将结果写入字符串缓冲区。所以它就像printf,但它不是打印到stdout,而是存储缓冲区

int sprintf( char* buffer, const char* format, ... );

缓冲区的大小应该足够大,以包含整个结果字符串,该字符串是字符+结尾处终止为null。您可以使用snprintf作为更安全的版本。

你有6778986,因为这是因为获得p ASCII个字符值" jpg" (终止' \ 0'),`0x0067706A'

'\0' 'g' 'p' 'j'
0x00  67  70  6A

什么告诉我们,您的picture很可能被错误地声明为

char picture[4];

因此没有足够的空间容纳8个字符的字符串"%03d.jpg" (+' \ 0')。

您应该将缓冲区声明为

char picture[8]; // space for at least 7 characters + '\0' 

答案 2 :(得分:2)

函数sprintf与函数printf类似,不同之处在于它将字符数组中的格式化数据输出为stdout而不是标准流printf

我认为问题在于,在调用sprintf之后,没有为变量picture分配足够的内存来存储结果字符串。所以程序会覆盖pic_num占用的内存。

如果您将尝试以下代码

#include <cstdio>

int main() 
{
    int pic_num = 1;
    std::printf( "pic_num = %i\n", pic_num );
    char picture[8];
    std::sprintf( picture, "%03d.jpg", pic_num );
    std::printf( "%s, pic_num = %i\n", picture, pic_num );

    return 0;
}

您将获得预期的结果

pic_num = 1
001.jpg, pic_num = 1