All this talk about do_ptr being slower because it copies from main memory is misleading. Yes, it's slower, because it's doing something different than what do_arr does. It's not just a slower version of doing the same thing. So trying to compare do_ptr and do_arr makes no sense. And the whole thesis of this piece, that declaring string constants as arrays is better, has no supporting evidence. You know what's better…
Wasn't that sort of the point or using arrays instead of pointers? There is less dereferencing to get to the data, so you need to dereference fewer pointers. I would like to see more empirical measurement in articles like this. There has to be a reason both compiler decided to emit that pointer based code, surely there is some advantage.
Declaring C String Constants
41–50 of 87 posts
Re: Declaring C String Constants
#42All this talk about do_ptr being slower because it copies from main memory is misleading. Yes, it's slower, because it's doing something different than what do_arr does. It's not just a slower version of doing the same thing. So trying to compare do_ptr and do_arr makes no sense. And the whole thesis of this piece, that declaring string constants as arrays is better, has no supporting evidence. You know what's better…
Wasn't that sort of the point or using arrays instead of pointers? There is less dereferencing to get to the data, so you need to dereference fewer pointers. I would like to see more empirical measurement in articles like this. There has to be a reason both compiler decided to emit that pointer based code, surely there is some advantage.
No, and that's why the article is confusing. It makes it seem like that's true but it's really not.
If you remove everything else and just look at passing the pointer itself, the fundamental difference between the pointer version and the array version is the pointer version isn't constant, and therefore has one level of indirection. This is because you can reassign to the `ptr` variable. But the array is constant, you can't reassign `ary`. All you really have to do here is put `const` on the `ptr` variable and suddenly you get the exact same code. Or in other words,
const char * const ptr = "Foo";
behaves the same way as const char ary[] = "Foo";
And the only practical difference between the two at this point is how the sizeof() operator works.Re: Declaring C String Constants
#43There's a big mistake here: // Bogus function, just to see how arguments are passed. void bogus(); // Invoke bogus using ptr. void do_ptr() { bogus(&ptr, ptr); } // Invoke bogus using arr. void do_arr() { bogus(&arr, arr); } "&ptr" and "&arr" are not the same. &ptr gives you a pointer to a pointer (char * *), but &arr just gives you a pointer to the array data. That's why the code is different. This would normally sh…
Additionally, he keeps talking about dereferencing the pointer, which I don't think is right. The pointer never gets deferenced in the code shown. I'm not an x86 guru, but I think that "movq ptr(%rip), %rsi" is different because ptr needs to be moved from relative to the instruction pointer (because it is on the stack, as a non-const variable).
$arr is copying the address of "arr", so it must use an immediate move (possibly 64-bit). It could also use RIP-relative with the "lea" (load effective address) instruction.
$ptr(%rip) is accessing memory, so it uses RIP-relative addressing with the "mov" instruction.
Re: Declaring C String Constants
#44There's a big mistake here: // Bogus function, just to see how arguments are passed. void bogus(); // Invoke bogus using ptr. void do_ptr() { bogus(&ptr, ptr); } // Invoke bogus using arr. void do_arr() { bogus(&arr, arr); } "&ptr" and "&arr" are not the same. &ptr gives you a pointer to a pointer (char * *), but &arr just gives you a pointer to the array data. That's why the code is different. This would normally sh…
It's not really variadic in the sense that you can't use va_start and friends to access the arguments. Instead, if the actual definition doesn't match the call, it's undefined behavior and the compiler can't catch it.
It really seems like the C standard maintainers and compiler vendors should just get together and sort that whole mess out. It can give you a few extra percent in some benchmarks, sure, and help C keep its mostly-deserved reputation as the fastest language, but the cost is huge.
If these non-type-checked functions are really useful in some very unusual use case, give it a special weird syntax. Don't make it the default and inflict it on everybody whether they want it or not.
Re: Declaring C String Constants
#45Earlier quoted context omitted.
Being a language not far form assembly shouldn't mean being broken and error prone.
I'm not sure what you mean by "broken". The programmer must provide 100% correct code, as in any language. It is harder to write secure code in C than in other languages, and in return you get near-maximum control over the program.
Re: Declaring C String Constants
#46Any programming language that needs an entire blog post about how to declare string constants "the right way" is a programming language that needs to disappear.
You're totally right. But wannabe C experts will never accept that. Stupid broken language. The only valid reason why it should be used is for legacy reasons.
> The only valid reason why it should be used is for legacy reasons.
Also there are many projects even today where C is the only choice, like embedded programming, some micro controllers only have a C compiler available.
Re: Declaring C String Constants
#47Earlier quoted context omitted.
It's not really variadic in the sense that you can't use va_start and friends to access the arguments. Instead, if the actual definition doesn't match the call, it's undefined behavior and the compiler can't catch it.
Undefined behavior strikes again! It really seems like the C standard maintainers and compiler vendors should just get together and sort that whole mess out. It can give you a few extra percent in some benchmarks, sure, and help C keep its mostly-deserved reputation as the fastest language, but the cost is huge. If these non-type-checked functions are really useful in some very unusual use case, give it a special wei…
Re: Declaring C String Constants
#48Re: Declaring C String Constants
#49Earlier quoted context omitted.
Why would it be a joke? Using `#define` for a string constant is perfectly reasonable for C code, IMO I'd argue it's the idiomatic and best way to do it. String constants that are `#define`d can take advantage of C's automatic string-literal concatenation, allowing you to avoid lots of unnecessary string operations in some cases. If you declare it as a pointer or array instead, then you can't do that.
> Why would it be a joke? A certain influential segment of the C and C++ development community, the kind that tends to worship "best practices" and "consistency", has been preaching for years that C preprocessor macros are evil, even in cases where they allow for much clearer code. I'm not sure these people were born with the ability to experience joy.
That said, yes they can lead to large gains so when they are worth it, go for them. Just mention in the documentation that they are macros, in big letters.
Re: Declaring C String Constants
#50Earlier quoted context omitted.
It's not really variadic in the sense that you can't use va_start and friends to access the arguments. Instead, if the actual definition doesn't match the call, it's undefined behavior and the compiler can't catch it.
Undefined behavior strikes again! It really seems like the C standard maintainers and compiler vendors should just get together and sort that whole mess out. It can give you a few extra percent in some benchmarks, sure, and help C keep its mostly-deserved reputation as the fastest language, but the cost is huge. If these non-type-checked functions are really useful in some very unusual use case, give it a special wei…
In fact not specifying a parameter list may make your code slower, as (IIRC) default argument promotions are always applied to parameters passed to such a function.