In my C program, I have a line where I am using the '==' operator, and the two operands are casted as char, like so:
char top_level_domain[sizeof(char) * 128];
...
if((char)top_level_domain[i] == ':'
|| (char)top_level_domain[i] == '/')
Is this recommended/safe? If not, how should I go about checking the contents of a certain element in an array?
EDIT: added declaration and removed casts to the character literals
A cast is a special operator that forces one data type to be converted into another. As an operator, a cast is unary and has the same precedence as any other unary operator. const_cast<type> (expr) − The const_cast operator is used to explicitly override const and/or volatile in a cast.
Cast operator: () A type cast provides a method for explicit conversion of the type of an object in a specific situation.
The operator used to perform cast operation in C# is parentheses. To perform a cast operation, the destination data type is explicitly written in parentheses before the value to be converted. An example for cast operation can be the conversion of a variable of double or float type to an integer type.
In general, it is more safe and effective to avoid casting when you can, because it allows the compiler to perform type checking. For example, spot the error:
// Let's pretend you forgot or mixed up the type here...
char **top_level_domain;
// ...
if ((char) top_level_domain[i] == (char) ':')
...
Or maybe...
char top_level_domain[sizeof(char) * 128];
...
// Whoops! forgot to type [i]
if((char)top_level_domain[i] == ':'
|| (char)top_level_domain == '/')
Whoops! You forgot to dereference the pointer, you're getting garbage. The compiler would have given you a diagnostic message, but since you used a cast, the diagnostic message is gone.
Note: This will actually cause a diagnostic message on some compilers because char
is narrower than char *
, but if we were using size_t
instead of char
then there would be no narrowing, but it would still be an error.
There are quite a few situations where the C "integer promotions" and "usual arithmetic conversions" can cause undesired behavior. For example,
size_t align_to_16_bytes(size_t x)
{
// return x & ~15u; // WRONG
return x & ~(size_t) 15u; // RIGHT
}
However, in general it will only cause problems when you are using types wider than int
or when you are mixing signed and unsigned types that are at least as wide as int
.
Newer languages such as Java and C# largely avoid this problem by only allowing widening implicit casts.
The casts are "safe" but useless, and very bad style. Generally in C, anything that needs a cast is at best bad style, and more often, invoking undefined behavior, so the presence of casts in a source file is a "code smell" - an indication that the author probably did something wrong and that the reader needs to be extra careful looking for bugs.
Just remove the casts and your code will be perfectly fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With