Home > Mobile >  What's the correct way to use scanf_s in using string arrays?
What's the correct way to use scanf_s in using string arrays?

Time:02-10

char array1[10];
scanf_s("%9s", array1, (unsigned)_countof(array1);

What's mean of (unsigned)_countof(array1)?

and what's different from use scanf_s("%9s", array1, sizeof(array1);?

both worked, but I want to understand about it more surely

CodePudding user response:

What's the correct way to use scanf_s in using string arrays?

scanf_s() with "%9s" is not for string arrays. It is for reading text and saving as a single string, which is a character array with a null character.

Its proper use is complicated by MSVC expects a different type in the count argument than C11. In C11 and later, scanf_s() is an optional function of the standard library and lacks wide acceptance.

// MSVC - type unsigned expected, hence the cast.
scanf_s("%9s", array1, (unsigned)_countof(array1);

// C11 - type size_t expected
scanf_s("%9s", array1, sizeof array1 / sizeof array1[0]);

Proper use of either obliges code to check the return value of scanf_s()

if (1 == scanf_s("%9s", ...)) Success();
else Fail();

What's mean of (unsigned)_countof(array1)?

_countof() is an MSVC macro equivalent to (sizeof(array) / sizeof(array[0])). When passed an array, it returns the count of elements in the array as type size_t. Casting to unsigned gets the expected type as with MSVC scanf_s(). The value may truncate due to the cast - a rare issue with huge arrays.


what's different from use scanf_s("%9s", array1, sizeof(array1));?

The expected type of sizeof(array1) is size_t and not unsigned as expected in MSVC - leading to undefined behavior. When size_t is as unsigned, that is OK, else a real problem.

The conceptual value is wrong. It should be the array element count, not the byte size of the array. Either OK here as sizeof(char)==1, yet wrong if code moved to say using wide characters.


both worked

Code is not portable. It may have "worked" in OP's case, but lacks portability.


Consider alternatives to scanf_s(), scanf() like fgets().

CodePudding user response:

sizeof and _countof are different. In this case you should use sizeof.

sizeof is an operator in C that returns the memory size occupied by a variable, in bytes. In this case, array1 is an array of 10 chars, so it's size is ten times the size of a char, and sizeof(char) is 1 byte. So the value of sizeof(array1) is 10 * 1 = 10 bytes.

Note that in C you can use sizeof on any variable (e.g. sizeof(array1)) or on any type (e.g. sizeof(int)).

_countof is a macro (only available on Microsoft platforms) that gives you the number of elements declared in an array variable. In this case your array1 variable has 10 elements, so _countof(array1) will be 10.

Now in your precise case this happens to be the same result because the size of each char is 1, but this wouldn't be the same if, for example, your variable was an array of ints.

int array2[10];

sizeof(array2);  // = 40 
_countof(array2); // = 10

An int is (usually) 4 bytes, so an array of 10 ints will have a size of 10*4 = 40 bytes. On the other hand, _countof will just count how many elements are declared in the array, and still return 10.

In fact, we can see that the definition of _countof is litterally sizeof(array) divided by sizeof(array[0]), that is, the size of an individual element.

Since scanf_s expects a size in bytes, you should be using sizeof.

You might also want to be careful with sizeof (and _countof) on arrays, and avoid using them on pointers. Also be aware that _countof will not work outside of Visual Studio. See these related answers.

CodePudding user response:

This question is compiler based, GCC 11.1.0 on Arch Linux does not have functions like scanf_s and _countof. These functions/macros might be valid in Windows.

I read some docs on Microsoft docs. So, _countof is a macro which calls sizeof() internally and scanf_s is similar to scanf in standard C17.

What's mean of (unsigned)_countof(array1)? and what's different from use scanf_s("%9s", array1, sizeof(array1);? both work, but I want to understand about it more surely

Here the macro _countof is counting the length of the stack stored array, which in this case is 10.

_countof macro expands to:

#define _countof(x) sizeof(x) / sizeof(x[0])
// the operation goes for `array1` like this:
// 10 * 1 byte / 1 byte
// 1 byte is the sizeof char
// hence, 10 is returned as the result of the above operation

And (unsigned) is just type casting the value of the above operation.

NOTE: As _countof is calling sizeof() do not use this inside a function the get the length of an array. Because sizeof(arr_ptr) will return the size of pointer which is 8 bytes in my case (x86_64 architecture).

Conclusion:

There no _countof is just calling sizeof(). I would like to suggest you to use sizeof and scanf functions because they are cross-platform and portable throughout the C standards.

  • Related