简体   繁体   中英

Is it ok to pass an int array to scanf and printf when using the %s specifier?

I stumbled upon a question with this code

int arr[10];
scanf("%s", arr);
printf("%s", arr);

I don't know the purpose, and I'm perfectly aware of how much this code smells. But my question here is if this i legal, and if I can expect it to reprint the string I enter? (Provided that the input string isn't so long that it causes buffer overflow)

And I also wonder if there's any example where this is actually useful.

From the C standard about fprintf https://port70.net/%7Ensz/c/c11/n1570.html#7.21.6.1p8

If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type.

and fscanf https://port70.net/%7Ensz/c/c11/n1570.html#7.21.6.2p12

If no l length modifier is present, the corresponding argument shall be a pointer to the initial element of a character array large enough to accept the sequence and a terminating null character, which will be added automatically.

And in this case, it's not a character array. But I seem to recall that there are some special rules about implicit conversions to and from char pointers, but I also have a memory that these does not apply to variadic functions.

For the language lawyer I would say it is illegal:

From C11: 7.21.6.

s If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type . 280)

and

9 If a conversion specification is invalid, the behavior is undefined. 282) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

For any practical use I would say that I cannot think of a scenario where it might fail as long as you don't enter more characters than fit into the array.

Update after question was extended:

But I seem to recall that there are some special rules about implicit conversions to and from char pointers, but I also have a memory that these does not apply to variadic functions.

Correct, implicit conversions can only happen if type of destination is known. For variadic functions no such conversion is done for pointers.

And also in those cases where an implicit conversion would be done, it is only possible if one of them is void * , not between int * and char * .

... that there are some special rules about implicit conversions to and from char pointers

No, that's not correct.

For void pointers you have implicit conversion but not for char pointers. In the very old K&R days (ie before "void" was introduced) char pointers were used as "the generic pointer" type but still there was no implicit conversion.

Maybe you are confusing conversion with aliasing. For aliasing char pointers are special as a char pointer is allowed to alias other object types.

The conclusion is that the code has undefined behavior. Passing an int pointer when a char pointer is expected is not standard compliant.

You are allowed to access an int or an array of int using char references; C 2018 6.5 7 says character types may be used to access an object.

However, for %s , scanf and printf should be passed a char * , not an int * . Even though a char * may be used (with dereferencing) to access an int or array of int , that does not mean an int * will serve in place of a char * . When scanf or printf attempts to get the char * they expect (as by using va_arg ), the fact that an int * was passed makes the behavior not defined by the C standard.

If instead you convert the int * to a char * :

scanf("%s", (char *) arr);
printf("%s", (char *) arr);

then the behavior is arguably defined by the C standard. (“Arguably” because the internals of scanf and printf are not formally specified. Presumably they align with the aliasing rules in 6.5 7.)

The program will run but with a warning explaining that %s expects the variable arr to be a char * type otherwise an array of char . So, the output will be the string that the user types on demand of the program...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM