我很多时候没有使用过C,现在我必须修改一小段代码。有一点我无法理解:
char filename[20];
filename[0] = '\0';
for (j=0; j < SHA_DIGEST_LENGTH; j++){
sprintf(filename + strlen(filename),"%02x",result[j]);
}
在第一行中,将显示一个包含20个字符的字符串。 在第二行中,第一个字符设置为'\ 0',我想是一个空字符串。
在for循环中我不明白文件名和它的长度之间的“总和”...... sprintf的第一个参数应该是一个缓冲区,在那里复制右边的格式化字符串。这笔款项的结果是什么?在我看来,我正在尝试将数组和整数相加...
我缺少什么?
答案 0 :(得分:13)
它是指针算术。 strlen
返回NUL终结符之前的字符数。添加的结果将指向此终结符。例如。如果当前字符串是“AA”(后跟NUL),则strlen为2. filename + 2
指向NUL。它将在NUL和下一个字符上写下一个十六进制字符(例如BB)。然后它将再次终止它(在filename + 4
)。那么你将拥有“AABB”(然后是NUL)。
但它确实没有意义。它浪费了很多时间寻找那些NUL。具体来说,它是一个二次算法。第一次,它检查1个字符,然后3,5,7,...,2 * SHA_DIGEST_LENGTH - 1)那个。它可能只是:
sprintf(filename + 2 * j,"%02x",result[j]);
还有另一个问题。 SHA-1和的十六进制表示需要40个字符,因为一个字节需要两个字符。然后,你有一个最终的NUL终结符,所以应该有41.否则,就会出现缓冲区溢出。
答案 1 :(得分:1)
第一次迭代,当j = 0
时,您将写入3个字符(是的,包括终止字符串的'\0'
)到filename
的开头,因为strlen()然后返回0。
下一轮,strlen()返回2,它将在前两个字符后继续写入。
小心踩到分配的20个字符空间。常见的错误是忘记字符串终止符所需的空间。
编辑:确保SHA_DIGEST_LENGTH不大于9.
答案 2 :(得分:1)
为什么不宣布
char filename[SHA_DIGEST_LEN*2 +1];
/ *如果你想让NULL终止char * /
这是因为SHA1摘要长度为20个字节,如果您只是打印摘要,那么您可能不需要额外的内存,但由于您需要摘要的十六进制字符串,您可以使用上述声明。 strlen操作返回字符串的长度,直到遇到空终止字符。
所以基本上当你执行以下操作时:
sprintf(filename + strlen(filename),"%02x",result[j]);
在第一次交互中,使用sha-1摘要的第一个字节的十六进制表示的2个字节复制filname。例如。假设这是AA,现在你需要将指针移动两个位置以复制下一个字节。
第二次迭代后,它变成了AABB。 在第20次迭代之后,你有整个字符串AABBCC ...... AA [40字节]和+1,如果你需要'\ 0'这是NULL终止字符。
答案 3 :(得分:0)
您只是添加strlen(filename)来进行result [j]
的连接每次迭代都会在文件名末尾连接当前结果[j],这样每次你需要知道在连接应该发生的文件名中的偏移量。
答案 4 :(得分:0)
将代码替换为:
char filename[SHA_DIGEST_LENGTH*2+1];
for (j=0; j < SHA_DIGEST_LENGTH; j++){
sprintf(filename + 2*j,"%02x",result[j]);
}
更快,更简单,错误消失了。