麻烦用'char * str + int'理解sprintf

时间:2016-11-22 02:39:34

标签: c++ printf

我正在查看一个项目并遇到了以下代码,我无法弄清楚sprintf在这种情况下正在做什么,并希望有人能够帮助我解决这个问题。

char storage[64];
int loc = 0;
int size = 35;

sprintf(storage+(loc),"A");  //Don't know what this does
loc+=1;
sprintf(storage+(loc),"%i", size);  //Don't know what this does
loc+=4;
sprintf(storage+(loc), "%i", start); //Don't know what this does

start += size;
loc += 3;

该代码稍后在另一部分中执行以下操作

string value;
int actVal;
int index = 0;
for(int j = index+1; j < index+4; j++)
{
    value += storage[j]; 
}
istringstream iss;
iss.str(value);
iss >> actVal; //Don't understand how this now contains size

我在网上看到的有关sprintf的例子从未涉及上述代码是可行的,但程序执行正常。我只是无法弄清楚“+ loc”如何影响此实例中的存储以及如何保存/存储值。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:0)

丑陋的代码!无论如何,对于第一部分,storage+(loc) == &storage[loc]。您最终会得到一个字符串"A35\0<unknown_value>1234\0",假设为start = 1234,或者是长格式:

sprintf(&storage[0],"A");
sprintf(&storage[1],"%i", size);
sprintf(&storage[5], "%i", start);

对于第二部分,假设我们上面有"A35\0<unknown_value>1234\0",我们得到:

 value += '3';
 value += '5';
 value += '\0';
 value += '<unknown_value>'; // This might technically be undefined behaviour

现在value = "35"。 [1]

iss.str(value);
iss >> actVal;

这会将字符串转换为输入流并读出表示整数"35"的第一个字符串,并将其转换为整数,基本上为actVal = atoi(value.c_str());提供。

最后,according to this page,是的,读取未初始化的(&#34;不确定的值&#34;是官方术语)数组元素是未定义的行为,因此应该避免。

[1]请注意,在通常的实现中,<unknown_value>可能包含ASCII数字的理论值为10/256,因此value最终可能介于350之间和359,这显然不是一个好结果,也是人们不应忽视未定义行为的原因。

答案 1 :(得分:0)

函数sprintf()的工作方式与printf()类似,但结果不会在stdout中打印,而是存储在字符串变量中。我建议你仔细阅读sprintf()手册页:

https://linux.die.net/man/3/sprintf

即使您不在Linux上,该功能在不同平台上也非常相似,无论是Windows,Mac还是其他动物。也就是说,您提供的这段代码似乎不必要地复杂化了。

第一部分可以写成:

sprintf(storage,"A %i %i", size, start);

对于类似但不相等的结果,但又一次,这完全取决于原始程序员究竟想要保存这个存储区域的内容。正如Ken指出的那样,有一些未定义的字节和行为来自这个代码。

答案 2 :(得分:0)

来自标准:

  

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

     

将格式化数据写入字符串   如果在printf上使用了格式,则使用相同的文本组成一个字符串,但不是打印,而是将内容作为C字符串存储在str指向的缓冲区中。

     

sprintf(storage+(loc),"A");

写&#34; A&#34;进入名为storage的缓冲区。 storage+(loc)是指针算术。您正在指定要写入的char数组的索引。所以,storage = "A"

  

sprintf(storage+(loc),"%i", size);

在这里,您将size写入存储[1]。现在storage = "A35\0"loc = 1等等。

您的最终价值为storage = "A35\0<garbage><value of start>\0"

  

actVal:不要理解现在这包含的大小

for循环遍历storage[1]storage[5],并使用value的内容构建storagevalue包含字符串"35\0<garbage>"iss.str(value)将其删除为"35\0"

  

iss >> actVal

如果您遇到std::cin,那就是相同的概念。包含整数值的第一个字符串将写入actVal。