代码之家  ›  专栏  ›  技术社区  ›  SF.

scanf(“%d”,char*)—char作为int格式字符串?

  •  2
  • SF.  · 技术社区  · 14 年前

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

    我想使用sscanf将一个永远不超过255(实际上要少得多)的数字读入无符号char类型变量。

    使用典型

     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 回复  |  直到 14 年前
        1
  •  4
  •   Hasturkun    14 年前

    你可以使用 %hhd 在glibc的统治下 scanf() ,msvc似乎不支持直接将整数存储到char中(请参阅msdn scanf Width Specification 有关支持的转换的详细信息)

        2
  •  1
  •   Dpp    14 年前

    使用它是危险的。由于存在从无符号char*到int*的隐式强制转换,如果数字大于0xff,则将使用堆栈中变量旁边的字节(max 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;
    
        3
  •  0
  •   Dummy00001    14 年前

    我想读一个数字从来没有 超过255(实际上要少得多) 转换为无符号字符类型变量 使用sSCANF。

    在大多数情况下,通过对整数使用char,可以节省一点到一点。

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

    这里增加了对非CPU字对齐内存访问的惩罚(不要问我为什么CPU会这样做),char的使用应该限于实际需要char或内存消耗的情况。

        4
  •  0
  •   Pavel Radzivilovsky    14 年前

    这是不可能的。

    SScanf在读取整数时永远不会写入单字节。

    如果将指向单个已分配字节的指针作为指向int的指针传递,则会超出界限。由于默认对齐,这可能是可以的,但您不应该依赖于此。

    创建临时文件。这样,您还可以运行时检查它。

        5
  •  0
  •   PeterK    14 年前

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

        6
  •  0
  •   MaR    14 年前

    这很危险。scanf将在字符大小的变量上写入整数大小的值。在您的示例中(很可能),除非重新组织堆栈变量,否则不会发生任何事情(在尝试写入整数大小的“dest”时,scanf将部分覆盖len,但随后它返回正确的“len”,并用“right”值覆盖len)。

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

     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
     }