我正在查看一个项目并遇到了以下代码,我无法弄清楚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”如何影响此实例中的存储以及如何保存/存储值。任何帮助将不胜感激。
答案 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
的内容构建storage
。 value
包含字符串"35\0<garbage>"
,iss.str(value)
将其删除为"35\0"
。
iss >> actVal
如果您遇到std::cin
,那就是相同的概念。包含整数值的第一个字符串将写入actVal。