我面临一个与sscanf一样奇怪的问题,当我按特定顺序传递参数时,我可以正确读取所有值,如果我更改顺序,它就可以正常工作。有人可以解释为什么这种奇怪的行为?
#include <stdio.h>
#include <stdint.h>
#include <string.h>
int main() {
uint8_t oct1, oct2, oct3, oct4;
char buf[20];
memset(buf, 0, sizeof(buf));
sprintf(buf,"%d.%d.%d.%d", 1, 2, 3, 4);
printf("%s\n", buf);
int f = sscanf(buf,"%d.%d.%d.%d", &oct4, &oct3, &oct2, &oct1);
printf("%d.%d.%d.%d \nSuccessfully read - %d\n", oct1, oct2, oct3, oct4, f);
return 0;
}
Output:
1.2.3.4
4.3.2.1
Successfully read - 4
memset()
答案 0 :(得分:5)
int
的正确格式说明符是来自uint8_t
的{{1}}宏。用法应该是:
SCNu8
同样,<inttypes.h>
和sscanf(buf,"%" SCNu8 ".%" SCNu8 ".%" SCNu8 ".%" SCNu8, &oct1, &oct2,
&oct3, &oct4);
分别为SCNu32
和SCNu16
,uint32_t
,uint16_t
,SCNd8
代表SCNd16
分别为1}},SCNd32
和int8_t
。
请注意,使用整数类型(在C99中引入)修复的这些是可选类型。
旁白:
int16_t
很危险,因为它们无法阻止缓冲区溢出。建议使用int32_t
代替:
sprint
此外,snprintf()
ing snprintf(buf,sizeof buf, "%d.%d.%d.%d", 1, 2, 3, 4);
是不必要的,因为你要立即写入它(注意memset()
总是NUL终止缓冲区。)
答案 1 :(得分:4)
在C中,类型int
可以在-32767~32767中保存至少整数,并且它不适合8位。
另一方面,uint8_t
被准确为8位。
出于这个原因,将uint8_t*
传递到int*
%d
格式的sscanf()
所需oct3
将导致类型不匹配,这是未定义的行为
两个程序都有相同的问题,因此&#34;工作案例&#34;只是偶然地工作。
我猜它&#34;工作&#34;因为机器是小端,oct4
的地址高于oct3
,所以oct4
的值在阅读oct2
时没有被破坏,同样的事情可以说oct1
和oct3
。
另一方面,如果您在此条件下阅读oct4
之前阅读oct3
,oct4
的值可能会被销毁为awk '/MemTotal/ && !memtotal { memtotal = $2 }
/MemFree/ && !memfree { memfree = $3 }
/Buffers/ &&!buffers { buffers = $4 }
/Cached/ && !cached { cached = $5 }
END (
# Ugh, is this really necessary?
print "-------------------"
print memtotal, memfree, buffers, cached
print " ****-------------------"
numsum=memfree+buffers+cached
print "numsum =MemFree+Buffers+Cached=" numsum
numminus=memtotal-numsum
print "numminus =MemTotal-(MemFree+Buffers+Cached)=" numminus
numDivide=numminus/memtotal
print "numDivide =numminus/memtotal=" numDivide }' /proc/meminfo
的数据部分。
答案 2 :(得分:0)
问题是您使用的变量的大小。 more
需要scanf
int*
个参数,并使用%d
。因此,当uint8_t*
写入变量时,它会溢出内存地址,而在非工作情况下,它会覆盖其他变量。发生这种情况是因为它们在内存布局方面彼此跟随。
它只发生在其中一种情况中,因为它取决于首先写入哪个变量(有效地覆盖先前的写入)。
要解决此问题,只需根据需要使用scanf
。