Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You're right and thanks for the correction. One point I'd add is that C generally encourages not using casts because casts themselves can be error-prone. So it's debatable whether it adds any real type-safety.


I don't see how it's debatable. The version without a cast is just plain incorrect, but happens to work anyway through luck and happenstance on many platforms. Even ignoring that, getting the types right without the cast requires looking at the type of every parameter, which could be variables declared far away, and understanding and applying C's vararg type promotion rules. Getting the types right for a cast just requires writing out those types correctly at the point of the cast.


I said you're right and I wasn't trying to disagree. I'm also a big fan of your blog and comments here (FWIW).

As for whether casts add much safety, I admitted it's debatable. C++ prefers casts (e.g. on malloc) whereas C doesn't. A downside of using explicit casts is that if the type changes elsewhere in the program, the casts (spread throughout the code) can mask errors. If you write code such that casts are unnecessary (which I'm agreeing is not possible in this case!), you will get a compile warning/error right away.

I think both perspectives are valid and there are risks either way. I try to avoid casts when writing plain C though.


I agree that unnecessary casts are undesirable, but that seems like a completely irrelevant point here, seeing as how the casts are not optional.

C++ doesn't prefer casts, it requires them in places where C doesn't. Casting the return value from malloc isn't optional in C++ (unless you're assigning to a void *, anyway).


I was referring to this part of your original post:

> It's also easy to make mistakes because of type mismatches. For example, if you pass `42` to a CGFloat parameter, this works fine when you cast msgSend to the right type, but will fail amusingly if you rely on varargs to make it through.

All of your other claims are completely valid. This one, I'd say, is partially valid.

No need to pick nits with my usage of the word "prefers."


I don't understand what's debatable about that. Maybe an example would help?

    objc_msgSend(window, sel_registerName("setAlphaValue:"), 1);
Versus:

    ((void (*)(id, SEL, CGFloat))objc_msgSend)(window, sel_registerName("setAlphaValue:"), 1);
The former will set a garbage alpha value, the latter works. More generally, the former requires much more care and attention to get the types right, whereas the latter just requires that the cast match the method declaration.


    ((void (*)(id, SEL, double))objc_msgSend)(window, sel_registerName("setAlphaValue:"), 1);
If the method signature changes (unlikely for a system header, but possible if you're calling into your own code) then you're hosed. Or you could just mess up and copy/paste the wrong signature, or forget to change it.

Basically, it's pretty error-prone no matter what you do. Using Objective-C directly is much safer (and luckily you usually can, since ObjC is pretty much a drop-in replacement for C).


I totally agree on all counts here. The cast saves you from this one specific thing but there's plenty more to go wrong. I think some people may overestimate the difficulty of adding some ObjC wrappers to a plain C project.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: