scanf(“%d”,char *) - char-as-int格式字符串?

时间:2010-06-14 10:14:27

标签: c csv format string-formatting

char-as-number的格式字符串修饰符是什么?

我希望使用sscanf读取一个不超过255(实际上更少)的数字到无符号字符型变量。

使用典型的

 char source[] = "x32";
 char separator;
 unsigned char dest;
 int len;

 len = sscanf(source,"%c%d",&separator,&dest);
 // validate and proceed...

我收到了预期的警告:sscanf的参数4是char *类型,int *是预期的。

据我了解规格,char没有修饰符(比如%sd表示简短,或%lld表示64位长)

  • 危险吗? (溢出只会溢出(翻转)变量,还是会在分配的空间外写入?)
  • 有没有比分配临时int变量更实用的方法?
  • ......或者你会建议一个完全不同的方法吗?

6 个答案:

答案 0 :(得分:4)

您可以在glibc的scanf()下使用%hhd,MSVC似乎不直接支持整数存储到字符中(有关支持的转换的详细信息,请参阅MSDN scanf Width Specification

答案 1 :(得分:1)

使用它是危险的。由于存在从unsigned char *到int *的隐式转换,如果该数字大于0xFF,它将使用堆栈中变量旁边的字节(最大3)并破坏它们的值。

%hhd的问题在于,根据int的大小(不一定是4个字节),它可能不是1个字节。

似乎sscanf不支持将数字存储到char中,我建议你使用int代替。虽然如果你想让char翻转,你可以在之后将int转换为char,如:

int dest;
int len;

len = sscanf(source,"%c%d",&separator,&dest);
dest = (unsigned char)dest;

答案 2 :(得分:0)

  

我想从未读过一个数字   超过255(实际上更少)   到unsigned char类型变量   使用sscanf。

在大多数情况下,通过使用char作为整数,您可以节省很少的东西。

它通常依赖于体系结构和编译器,但是大多数现代CPU在处理与寄存器大小不同的数据类型方面不是很好。 (值得注意的例外是64位arch上的32位int。)

在这里添加对非CPU字对齐的内存访问的惩罚(不要问我为什么CPU这样做)char的使用应限于真正需要char或内存消耗的情况。

答案 3 :(得分:0)

这是不可能的。

sscanf在读取整数时永远不会写单个字节。

如果将指向单个已分配字节的指针作为指向int的指针传递,则将超出范围。由于默认对齐,这可能是好的,但你不应该依赖它。

创建一个临时的。这样你也可以运行时检查它。

答案 4 :(得分:0)

最简单的方法可能是将数字简单地加载到一个临时整数中,并且只有当它在所需的边界内时才存储它。 (你可能需要像unsigned char result = tempInt & 0xFF;

这样的东西

答案 5 :(得分:0)

这很危险。 Scanf将在字符大小的变量上写入整数大小的值。在你的例子中(最有可能)除非你重组你的堆栈变量,否则什么都不会发生(scanf会在尝试写整数大小的“dest”时部分覆盖len,但是它会返回正确的“len”并用“right”值覆盖它)。

相反,做“正确的事”而不是依赖于编译器的情绪:

 char source[] = "x32";
 char separator;
 unsigned char dest;
 int temp;
 int len;

 len = sscanf(source,"%c%d",&separator,&temp);
 // validate and proceed...

 if (temp>=YOUR_MIN_VALUE && temp<=YOUR_MAX_VALUE) {
   dest = (unsigned char)temp;
 } else {
   // validation failed
 }