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 int
s.
int array2[10];
sizeof(array2); // = 40
_countof(array2); // = 10
An int
is (usually) 4 bytes, so an array of 10 int
s 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.