1

snprintf在循环中不起作用,linux但它在windows.

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

    int main( int argc, char **argv) {
      char buffer[255] ={0};
      for ( int i = 0; i < 10; i++) {
        snprintf(buffer, 255, "%s:%x\0",buffer,  i );
      }
      printf ( "BUFFER  = %s\n", buffer );
      return 0;
    }

此代码不附加现有的buffer,但只采用最后一次迭代值。

4

5 回答 5

5

您可以避免将缓冲区用作目标字符串和作为这样的参数的未定义行为:

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

int main( int argc, char **argv) {
  char buffer[255] ={0};
  int offset = 0;
  for ( int i = 0; i < 10; i++) {
    offset += snprintf(buffer + offset, 255 - offset, ":%x\0", i);
  }
  printf ( "BUFFER  = %s\n", buffer );
  return 0;
}
于 2012-07-30T09:30:35.343 回答
3

sprintf()将结果数组添加到自身是未定义的行为。

编辑:如果你想要一些有效的代码,你在这里:使用strcat()(或更安全的 strncat 等。在此处插入关于缓冲区溢出的常规安全讨论):

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

int main( int argc, char **argv) {
    char buffer[255] = { 0 };
    char fmtbuf[64];

    int i;
    for (i = 0; i < 10; i++) {
        snprintf(fmtbuf, 64, "%x", fmtbuf, i);
        strcat(buffer, fmtbuf);
    }

    printf ("BUFFER  = %s\n", buffer);
    return 0;
}

另请注意, printf() 调用不需要手动写出终止零 - 它是自动添加的。

于 2012-07-30T09:28:23.690 回答
1

snprintf确实按照 Linux 上的指定工作,但您的代码不会附加它。阅读链接文档中的注释!

您不应将目标用作其参数(在格式字符串之后)。

如果您希望它追加,请确保您不会溢出固定缓冲区,或者在该缓冲区变得太小时时重新分配该缓冲区。

于 2012-07-30T09:26:30.233 回答
0

您不能通过“snprintf”将“缓冲区”写入自身。

测试代码如下:

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

int main( int argc, char **argv) {
    char buffer[255] ={0};
    for ( int i = 0; i < 10; i++) {
        char tmp[255] = {0};
        strcpy(tmp, buffer);
        snprintf(buffer, 255, "%s:%x\0",tmp,  i );
        printf ( "BUFFER  = %s\n", buffer );
        }
    printf ( "BUFFER  = %s\n", buffer );  
    return 0;
}
于 2012-07-30T09:37:34.440 回答
0

该标准明确指出,该代码预计不会起作用。首先,声明了初始缓冲区参数restrict,这意味着它不能为另一个参数起别名。其次,本标准有以下条款只是为了强调:

7.19.6.5 snprintf 函数

描述

2 - [...] 如果复制发生在重叠的对象之间,则行为未定义。

于 2012-07-30T09:50:24.473 回答