变量顺序对sscanf有影响吗?

时间:2015-12-20 07:31:19

标签: c scanf

我面临一个与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()

3 个答案:

答案 0 :(得分:5)

int的正确格式说明符是来自uint8_t的{​​{1}}宏。用法应该是:

SCNu8

同样,<inttypes.h>sscanf(buf,"%" SCNu8 ".%" SCNu8 ".%" SCNu8 ".%" SCNu8, &oct1, &oct2, &oct3, &oct4); 分别为SCNu32SCNu16uint32_tuint16_tSCNd8代表SCNd16分别为1}},SCNd32int8_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时没有被破坏,同样的事情可以说oct1oct3。 另一方面,如果您在此条件下阅读oct4之前阅读oct3oct4的值可能会被销毁为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