Since we have snprintf, why we don't have a snscanf?

前端 未结 6 1066
名媛妹妹
名媛妹妹 2020-12-14 10:16

I have snprintf and it can avoid a buffer overflow, but why there is no function called snscanf?

Code:

int main()
{
     ch         


        
6条回答
  •  无人及你
    2020-12-14 10:47

    There's no need for an snscanf() because there's no writing to the first buffer argument. The buffer length in snprintf() specifies the size of the buffer where the writing goes to:

    char buffer[256];
    
    snprintf(buffer, sizeof(buffer), "%s:%d", s, n);
    

    The buffer in the corresponding position for sscanf() is a null-terminated string; there's no need for an explicit length as you aren't going to write to it (it's a const char * restrict buffer in C99 and C11).

    char buffer[256];
    char string[100];
    int n;
    if (sscanf(buffer, "%s %d", string, &n) != 2)
        ...oops...
    

    In the output, you are already expected to specify the length of the strings (though you're probably in the majority if you use %s rather than %99s or whatever is strictly appropriate):

    if (sscanf(buffer, "%99s %d", string, &n) != 2)
        ...oops...
    

    It would be nice/useful if you could use %*s as you can with snprintf(), but you can't — in sscanf(), the * means 'do not assign scanned value', not the length. Note that you wouldn't write snscanf(src, sizeof(buf1), "%s", buf1), not least because you can have multiple %s conversion specifications in a single call. Writing snscanf(src, sizeof(buf1), sizeof(buf2), "%s %s", buf1, buf2) makes no sense, not least because it leaves an insoluble problem in parsing the varargs list. It would be nice to have a notation such as snscanf(src, "%@s %@s", sizeof(buf1), buf1, sizeof(buf2), buf2) to obviate the need to specify the field size (minus one) in the format string. Unfortunately, you can't do that with sscanf() et al now.

    Annex K of ISO/IEC 9899:2011 (previously TR24731) provides sscanf_s(), which does take lengths for character strings, and which might be used as:

    if (sscanf_s(buffer, "%s %d", string, sizeof(string), &n) != 2)
        ...oops...
    

    (Thanks to R.. for reminding me of this theoretical option — theoretically because only Microsoft has implemented the 'safe' functions, and they did not implement them exactly as the standard requires.)

    Note that §K.3.3 Common definitions says: '... The type is rsize_t which is the type size_t.385)' (and footnote 385 says: 'See the description of the RSIZE_MAX macro in .' That means that in fact you can pass size_t without needing a cast — as long as the value passed is within the range defined by RSIZE_MAX in . (The general intention is that RSIZE_MAX is a largish number but smaller than SIZE_MAX. For more details, read the 2011 standard, or get TR 24731 from the Open Standards web site.)

提交回复
热议问题