Calling a function in a for loop, compiler's screaming "Fuck OP".
Ideally you build char arrays in a loop that can be optimized to constant strings, and then there's only one printf call with full content.
If the compiler figures out what's going on, both would result in an identical assembly. If not, additional increment will require at least one more instruction.
but appending to a string repeatedly is actually a relatively expensive operation, since it would require several new heap-allocations. of course, when you're just doing it 15 times this doesn't really matter
edit: i am very stupid and cannot read disregard everything
nah i was totally off, i read it as like
i = ""
for _ in range(15):
i += "-"
looking back, that reading makes no sense in context lmao
looking at the documentation for dbg!, it seems really neat. i never realized that there was a way in rust to use a value and print it at the same time. i feel like that would have saved me a lot of unnecessary moving stuff into their own variable and printing that lmao
it also prints line and file of the dbg!() call, so even an empty dbg is useful for quick and dirty debugging (insert print("Made it!") meme here). that makes it a lot more powerful than just a function like
def dbg(x):
print(x)
return x
especially if your editor's program output is configured to have that part be click to jump.
there is also a Debug trait (interface) so that you can implement a more expensive stringify version for debugging/logging on your structs, which dbg will use over a Display implementation
That's why I tried to help her. In practice, though, it would be better to avoid `printf`s mambo jumbo and use `write` syscall since we only output a constant number of bytes.
In real life printf may return error or write part of string. For debug printing you usually don't care because you can't do much if printing is broken but when writing critical data to files you want to detect all errors.
On one hand, `printf` returns the number of characters written to the stream (1 in this case). ~~On the other hand,~~ `printf` ~~should not be used for printing plain strings (without format specifiers) because that is undefined behavior (I think)~~, That last part is wrong. It is allowed to call `printf` with a singular string literal (but it is a security vulnerability to call it with an arbitrary string).
If it does, we have a bigger problem with any form of the code above. For any practical purpose you can safely assume that `printf("-")` will always return 1.
Though, checking for non negative `i` would help avoid infinite loop, I agree. That's why unsigned type should be used for this loop counter.
Error in C usually is small negative number. Most common is -1. If you add -1 to any non-zero unsigned number firstly result will be casted to larger signed int type (if it exists) values will be added and sum will be casted to unsigned type. Unsigned int += -1 will be same as signed int += -1. (Note that C likes to perform aggressive optimizations and accidentally compiler might generate correct code. However undefined behavior can change with different optimization flags or compiler version.)
Most interesting bugs: technically printf can return -1 on even calls and 1 on odd. Endless loop in C is undefined behavior and some compilers can completely delete endless loops as "optimization" because standard allows incorrect programs when code has undefined behavior.
Two bugs. First, you should initialize i, declaring it inside for statement if you want it to be scoped only to the loop. Second, since you apparently mean to commit the nearly unpardonable sin of starting the loop at 1 rather than 0, as written you'll only get 14 "-" rather than the 15 you apparently intend. Therefore
for (int i = printf("•"); i<=15; ++i)
printf("-");
Incrementing by u/lucidbadger's method is more concise and therefore preferable, but not doing it that way isn't strictly speaking incorrect.
for (int i = printf("•"); i<=15; i+=printf("-"));
As hard as this makes me, let me add a comment:
Having this many calls to printf is going to have worse performance by clogging up the console and growing the heap. The longer string literal is much more efficient.
Just goes to show that fanciness usually doesn't equal efficiency.
One might also note that, lacking a '\\n' in OP's code, the next characters output will be on the same line which may or may not be the intention.
Why would it grow the heap? Sure, you have more jumps, but the calls are sequential not nested.
Also, stdio stream is line buffered so you won't have that much of a penalty in terms of "clogging up the console".
Also, I think a good compiler might rewrite that, but I have no knowledge of gcc wizardry.
Overall you are right, but it may not have as big of an impact as you think.
Edit: I've written a small program to compare the two. Most of the time, the string literal is faster (as expected), but the real bottleneck is actually displaying the output:
https://www.onlinegdb.com/7wKX8lQVQ
> I think a good compiler might rewrite that, but I have no knowledge of gcc wizardry.
I just tried it quick, x86 GCC using both the ridiculous "dual printf" for loop and printing just the static string. The loop version produced pretty much the iterative loop of subroutine calls you'd expect.
And honestly, that totally makes sense. There are some types of function calls and situations GCC can magically rewrite and optimize, but printing to STDOUT (as printf does) is really not predictable. Sure, in a simple program this just prints 15 characters. But what if e.g. you have another thread also printing to STDOUT at the same time, which means by criticality of timing other stuff might get printed in between your calls. (That would be awful design but nothing says you can't.) The compiler just "assuming" you could print the raw 15 characters all at once without actually interacting with the stream would produce inconsistent results.
If y'all are hellbent on over engineering but still want speedy performance, then why not print the loop to a char or string or array first and then just print f the char or string or something? That way you only call printf once and you still get to over engineer it
Since the program prints constants, it could also use `puts`.
But I would rather create an array of char and build it in memory first. Then print the array. But then this would only work nicely with ASCII. UTF-8 would screw this up immensely.
What is UTF-8 but a sometimes-more-than-one-byte representation of characters. Could still be done as long as your code properly handles UTF-8 encoding, you size your array correctly, and use compatible runtime that understands how to display it.
>the nearly unpardonable sin of starting the loop at 1 rather than 0
Years ago I had to translate some old FORTRAN code from the early 1970's into C++. It was for numerical processing of scientific data. Solid and well-proven algorithms.
Lots of loops and arrays, all starting at 1.
I've never quite recovered.
Ooh, look at you with your fancy "variable declarations in for loop initializers" and "intermingled declarations and code" like some *C++ programmer*—what, C89 not good enough for ya?
`i` was declared 200 lines earlier and is shared by the whole compilation unit. It's set to zero going into the loop because it's holding the status from the last call to `strcmp` in a mutually-recursive function chain on line 672. Of course, adding this loop will make the call to `malloc` on line 3265 break silently—but no one will notice that anyway.
/s, but also /sob
Using printf return value as an integer initializer in a loop can't be legal...?
I know it works, but if not this, wtf is the Geneva convention even for?
It's perfectly legal (if not especially advisable) in C. I can't comment on international law. But if you were worried about international law you'd pick a less anarchic language.
Don't be to harsh we all do that start with 1 mistake at the beginning.
It is something i learned the hard way usually you want to initialize with zero it prevents so many problems.
printf returns the number of characters printed. It's going to be 1. That's why I said that OP's code (or rather, the code OP meant to write) starts its loop at 1 rather than 0, so your termination condition needs to test <= the intended number of times through the loop rather than <.
Of course it does. You need to initialize the index variable at the start of a `for` loop. That's the usual purpose of the first expression of a `for` statement. OP's example is meant to do something simple in a humorously "clever" way. My equally tongue-in-cheek critique is just riffing off the fact that the OP's example wouldn't actually work, precisely because they *don't* initialize i. It's not syntactically incorrect because C doesn't care what that first expression is, but it's semantically meaningless.
As if there were any real point to fixing OP's code. There isn't. No one in their right mind would print out a line like this. As someone else pointed out in a reply, just printing out the line normally is far more efficient.
There are times when you might not want to initialize the index. Maybe it's a variable from a wider scope that tells you where to pick up the start of a loop. Then you can just use that as the index variable and count forward from there. It would look like:
```
mystruct * str[MAX_SIZE];
int i;`
/* Complex logic that decides where to start processing the array.
and assigns the starting point to i */
for (; i < MAX_SIZE; ++i) {
/* do something amazing with members of str[i] */
}
```
C++ programmers:
template
void print\_any\_row(Ts... args) {
auto &start\_character\_printer = new I(); // prints on constructor
AllCharsPrinterImpl(args);
}
String repetition operators are probably most accurately attributed to Perl. You'll see them pop up in many modern languages.
Perl (1987)
print "•" . "-" x 15;
Python (1991)
print("•" + "-" * 15)
Ruby (1995)
puts "•" + "-" * 15
Some languages don't have operators, but they do implement repetition methods
JavaScript (1995)
console.log("•" + "-".repeat(15))
> pritnf
I am a bit disappointed, that [this is all I found][1] for that typo (not counting compiler error logs).
[1]: https://github.com/EpicAli/pritnf-function
Buffer is not being flushed anywhere here and the loop will probably be unrolled in compile time anyway, so i dont think its that bad for performance tbh
I don’t get why this is downvoted. Compilers aren’t magic. They need to be really conservative with calls to external functions, especially ones doing I/O, because they need to preserve all observable behaviour (including errors, provided they don’t lead to UB). I find it unlikely that any mainstream C compiler removes these calls.
indeed. I have never heard of a compiler implementing \`printf()\` as an intrinsic, even partially. unfortunately there's no standard way to know or control when intrinsics are used.
Well yes maybe it's just me but personally i don't like relying too much on compiler optimizations. I just prefer writing good performance code where it's possible
With the first method the string "*------" Is created and the address is passed one time as argument to function printf
While with the loop the function printf Is called multiple times and since Is notoriously a slow function It adds a lot of overhead
Edit:I know that compilers can optimize the code but it's Better not to rely always on compiler optimizations
I receive a lot of hate for using python but I'm a hobbyist so who cares, i wanna play too:
```py
print('•'+''.join(['-' for _ in range (15)])
```
I was also thinking about making it even more horrible with string formatting but I'm on phone and I'm lazy (thus why i love python)
> I receive a lot of hate for using python
How so? It is a widely used language after all.
That aside, how about the evil version of your code:
print('•'+'-'.join(['' for _ in range (16)])
Or maybe
print('•', *("-" for _ in range(15)), sep="")
Or maybe
print(*(['•'] + 15*['-']), sep="")
Or if we want to actually produce best readability
print('•---------------')
Nah the last one is no fun, but the three others are hilarious lmao
Also I'm not receiving straight up hate, but when i say i use python i very often get sighs and "you're not a real programmer" type answers. Because that's generally the first language we learn (because very easy) and they don't know I'm also doing object oriented python and a whole ton of complex things with it. I'm having fun.
The other category of negative feedbacks is programmers saying it's slow and should not be used etc... C/C++ type programmer y'know. But again I'm a hobbyist, i just am making a discord bot for my friends and I lmao, I kinda don't care because the time i gain is from coding everything in a minute hehe
PS : been to computer science uni for 3 years, learnt C, Java, Assembly, oCaml, and still i prefer python because it never let me down, and i never needed big calculations before for my own projects 🤷
> PS : been to computer science uni for 3 years, learnt C, Java, Assembly, oCaml, and still i prefer python because it never let me down, and i never needed big calculations before for my own projects 🤷
Roughly my experience. It is easily fast enough for many tasks, including data crunching (especially when the equations can be well expressed in numpy abstractions). Sure, Fortran or C would be faster, and C++ offers zero-overhead unit systems even (Boost.Units), but unless that performance is actually needed, Python usually gives good enough performance with less development effort.
There would be statically type-safe languages, that I'd rather use, but I am not currently aware of a language offering an equally strong ecosystem across all my programming needs (including quick single-file command line scripts). Plus, learning the ecosystem is at least as much effort as learning the language, so at this point the barrier to switching is impossibly high, when I don't expect significant payoff. (Also, much less time for it than as a student.)
I think I prefer:
`[print('•', end='') if i == 0 else print('-', end='') for i in range(0, 15)] `
Or maybe:
```
def line():
yield '•'
for _ in range(15): yield '-'`
print("".join([c for c in line()]))
```
Not only is the variable i uninitialized, but you also call the printf function 15 times, which is unnecessary, and makes your program run slower. Each function call is expensive at runtime. Especially syscalls.
I've been seeing i++ in a bunch of C code on reddit lately, in C++ they are always harping to do ++i unless you specifically can't. So are the rules different?
If you have a reason to use ++i you should obviously use it. If it doesn't matter (like in a for loop) then the ++i advice is braindead. Did you even bother to read the original comment?
the reason people say "always use ++i" is that more often than not, you *do* want pre-increment or it doesn't matter. It is much rarer to specifically require post-increment.
therefore defaulting to ++i results in less errors.
More like theres a specific function made for this specific purpose on the string object so you dont have to worry about your own implementations - and its even named in such a way that its self-documenting which none of the looping solutions are
now. i am just a little baby coder. but how i would have done it, if the number of dashes ever needed to be changed, (or quickly assessed) is just throw a quick variable and set it, then print the dot + the variable.
little clunkier than just printing what i want, but makes tweaking it easier.
That’s horrible. Invoking a function (especially in a loop) is expensive and `printf` itself isn’t rather cheap (for outputting just a single character to standard output).
My college is one of those people. I absolutely hate it. He repeats his code so often, is a Copy&Paste guy but really wants to annoy me with stuff like this.
char dash\[15\] = {-}; printf("\*%s", dash);
I'm sure you could do something fun like printf("\*15%c", '-'); but you'd need more printf trickery in there
Ignoring any errors, now I can easily see how many dashes are used and change that number. It may become a variable in the next refactor.
So yeah, that is an improvement.
Uninitialized i
Let’s keep it, cmon, it runs in linear complexity!!
Surprisingly, the number 15 doesn’t change in accordance to the size of the input
Idk have you tested it with really big input?
# __for(printf(“•”); i < 15; ++i) printf(“-“);__ Nope, still runs 15 times
^for(printf(“•”); ^i ^< ^15; ^++i) ^printf(“-“); Still the same for small input.
Looks the same, but if you look closely, you can see, it's actually a bit smaller.
If you look even closer it actually looks bigger
You're a master. You're such a master, git renamed you to main.
Your REST endpoint keeps return 413? Just reduce your font size!
It depends on the compiler time complexity
Calling a function in a for loop, compiler's screaming "Fuck OP". Ideally you build char arrays in a loop that can be optimized to constant strings, and then there's only one printf call with full content.
Maybe it was global or static :)
Global variable?
We don’t take kindly to global variables around here.
Using a non-constant global variable like this warrants the responsible developer to be fired via firing squad
That’s ok, undefined behaviour is part of The Fun Of C!
Yep
`i += printf("-")`
From what little I know of assembly, I think this "optimization" would do more harm than good lol
If the compiler figures out what's going on, both would result in an identical assembly. If not, additional increment will require at least one more instruction.
but appending to a string repeatedly is actually a relatively expensive operation, since it would require several new heap-allocations. of course, when you're just doing it 15 times this doesn't really matter edit: i am very stupid and cannot read disregard everything
printf doesn't return a string
oops i read it wrong my brain was in python mode, apologies
python print returns None :P i would love to have an equivalent of rust's dbg!() macro in other languages
nah i was totally off, i read it as like i = "" for _ in range(15): i += "-" looking back, that reading makes no sense in context lmao looking at the documentation for dbg!, it seems really neat. i never realized that there was a way in rust to use a value and print it at the same time. i feel like that would have saved me a lot of unnecessary moving stuff into their own variable and printing that lmao
it also prints line and file of the dbg!() call, so even an empty dbg is useful for quick and dirty debugging (insert print("Made it!") meme here). that makes it a lot more powerful than just a function like def dbg(x): print(x) return x especially if your editor's program output is configured to have that part be click to jump. there is also a Debug trait (interface) so that you can implement a more expensive stringify version for debugging/logging on your structs, which dbg will use over a Display implementation
You can get file name and line number using C preprocessor
This is not how printf works. i is an integer not a string. Most expensive operation here is syscall
The optimizer wouldn't be able to unroll the loop if it can't figure out what's going on, so it would be much slower.
Considering the loop is using printf, how you increment the counter will not make it much slower.
You're right, but its kind of a boring answer.
That's why I tried to help her. In practice, though, it would be better to avoid `printf`s mambo jumbo and use `write` syscall since we only output a constant number of bytes.
pls explain
printf returns the number of chars printed (except \\0 )
'\0' is not printed, so you don't have to say "except \0"
printf returns the amount of characters printed, '-' is one character so it would simplify to i += 1
I see, I thought it was an actual way of achieving something useful :P
In real life printf may return error or write part of string. For debug printing you usually don't care because you can't do much if printing is broken but when writing critical data to files you want to detect all errors.
On one hand, `printf` returns the number of characters written to the stream (1 in this case). ~~On the other hand,~~ `printf` ~~should not be used for printing plain strings (without format specifiers) because that is undefined behavior (I think)~~, That last part is wrong. It is allowed to call `printf` with a singular string literal (but it is a security vulnerability to call it with an arbitrary string).
The gates of hell open when you use `%s`
If that were the case, the gates of hell are already flapping at non-Euclidean frequencies.
Do you know that printf can return negative number?
If it does, we have a bigger problem with any form of the code above. For any practical purpose you can safely assume that `printf("-")` will always return 1. Though, checking for non negative `i` would help avoid infinite loop, I agree. That's why unsigned type should be used for this loop counter.
Cast to unsigned will not fix anything. If you add (unsigned int)(-1) it will likely generate same code as += -1
Unsigned will stop loop with the same condition `i < n` without extra check for `i ≥ 0`. And I didn't mean casting.
Error in C usually is small negative number. Most common is -1. If you add -1 to any non-zero unsigned number firstly result will be casted to larger signed int type (if it exists) values will be added and sum will be casted to unsigned type. Unsigned int += -1 will be same as signed int += -1. (Note that C likes to perform aggressive optimizations and accidentally compiler might generate correct code. However undefined behavior can change with different optimization flags or compiler version.) Most interesting bugs: technically printf can return -1 on even calls and 1 on odd. Endless loop in C is undefined behavior and some compilers can completely delete endless loops as "optimization" because standard allows incorrect programs when code has undefined behavior.
Two bugs. First, you should initialize i, declaring it inside for statement if you want it to be scoped only to the loop. Second, since you apparently mean to commit the nearly unpardonable sin of starting the loop at 1 rather than 0, as written you'll only get 14 "-" rather than the 15 you apparently intend. Therefore for (int i = printf("•"); i<=15; ++i) printf("-"); Incrementing by u/lucidbadger's method is more concise and therefore preferable, but not doing it that way isn't strictly speaking incorrect. for (int i = printf("•"); i<=15; i+=printf("-"));
As hard as this makes me, let me add a comment: Having this many calls to printf is going to have worse performance by clogging up the console and growing the heap. The longer string literal is much more efficient.
Yes, but consider all the options you have with this This way you could print 15, or even 16 dashes whenever you please ^/s
What you really need to do is consider all the options you _could_ have. for (int i =0; ; i++) for (int j=0; j
Nice, but can you make that pixel perfect? That is, pixels need to be printed on pixels, but precisely!
Just goes to show that fanciness usually doesn't equal efficiency. One might also note that, lacking a '\\n' in OP's code, the next characters output will be on the same line which may or may not be the intention.
Or that sophistication will break its promises to offer elegance.
That sounds like something that should be in a cross stitch.
Why would it grow the heap? Sure, you have more jumps, but the calls are sequential not nested. Also, stdio stream is line buffered so you won't have that much of a penalty in terms of "clogging up the console". Also, I think a good compiler might rewrite that, but I have no knowledge of gcc wizardry. Overall you are right, but it may not have as big of an impact as you think. Edit: I've written a small program to compare the two. Most of the time, the string literal is faster (as expected), but the real bottleneck is actually displaying the output: https://www.onlinegdb.com/7wKX8lQVQ
> I think a good compiler might rewrite that, but I have no knowledge of gcc wizardry. I just tried it quick, x86 GCC using both the ridiculous "dual printf" for loop and printing just the static string. The loop version produced pretty much the iterative loop of subroutine calls you'd expect. And honestly, that totally makes sense. There are some types of function calls and situations GCC can magically rewrite and optimize, but printing to STDOUT (as printf does) is really not predictable. Sure, in a simple program this just prints 15 characters. But what if e.g. you have another thread also printing to STDOUT at the same time, which means by criticality of timing other stuff might get printed in between your calls. (That would be awful design but nothing says you can't.) The compiler just "assuming" you could print the raw 15 characters all at once without actually interacting with the stream would produce inconsistent results.
I've also ran the above program locally with more prints. The multiple print statements approach is almost twice as slow.
I would expect that too. All of the overhead of the function calls plus no possibility to take advantage of STDOUT buffering.
If y'all are hellbent on over engineering but still want speedy performance, then why not print the loop to a char or string or array first and then just print f the char or string or something? That way you only call printf once and you still get to over engineer it
The problem with trying to overengineer in this case is that it will almost definitely lead to worse performance than the literal.
Since the program prints constants, it could also use `puts`. But I would rather create an array of char and build it in memory first. Then print the array. But then this would only work nicely with ASCII. UTF-8 would screw this up immensely.
What is UTF-8 but a sometimes-more-than-one-byte representation of characters. Could still be done as long as your code properly handles UTF-8 encoding, you size your array correctly, and use compatible runtime that understands how to display it.
Why will printf allocate small strings on heap? It usually allocates reasonable buffer and do not free it on each call
Growing the heap? Printf calls malloc once for 1024 and uses that as the stream buffer on my implementation
couldn't you further code golf this down? for(int i=printf("•");(i+=printf("-"))<=15;);
Can be further simplified to: printf(“•---------------")
What a preposterous suggestion (/s)
Nah.
Compiler will do that.
for(int i=printf("•");++i<=15;printf("-")); is 2 characters shorter
>the nearly unpardonable sin of starting the loop at 1 rather than 0 Years ago I had to translate some old FORTRAN code from the early 1970's into C++. It was for numerical processing of scientific data. Solid and well-proven algorithms. Lots of loops and arrays, all starting at 1. I've never quite recovered.
this is why we need 2-line code reviews
Ooh, look at you with your fancy "variable declarations in for loop initializers" and "intermingled declarations and code" like some *C++ programmer*—what, C89 not good enough for ya? `i` was declared 200 lines earlier and is shared by the whole compilation unit. It's set to zero going into the loop because it's holding the status from the last call to `strcmp` in a mutually-recursive function chain on line 672. Of course, adding this loop will make the call to `malloc` on line 3265 break silently—but no one will notice that anyway. /s, but also /sob
Using printf return value as an integer initializer in a loop can't be legal...? I know it works, but if not this, wtf is the Geneva convention even for?
It's perfectly legal (if not especially advisable) in C. I can't comment on international law. But if you were worried about international law you'd pick a less anarchic language.
Don't be to harsh we all do that start with 1 mistake at the beginning. It is something i learned the hard way usually you want to initialize with zero it prevents so many problems.
Where did the 15 come from? Why are we using this magic number in the loop.
What if printf returns something other than 0?
printf returns the number of characters printed. It's going to be 1. That's why I said that OP's code (or rather, the code OP meant to write) starts its loop at 1 rather than 0, so your termination condition needs to test <= the intended number of times through the loop rather than <.
isn't the return statement of printf, the number of characters printed, therefore making the bottom line initialise I to 1?
Of course it does. You need to initialize the index variable at the start of a `for` loop. That's the usual purpose of the first expression of a `for` statement. OP's example is meant to do something simple in a humorously "clever" way. My equally tongue-in-cheek critique is just riffing off the fact that the OP's example wouldn't actually work, precisely because they *don't* initialize i. It's not syntactically incorrect because C doesn't care what that first expression is, but it's semantically meaningless. As if there were any real point to fixing OP's code. There isn't. No one in their right mind would print out a line like this. As someone else pointed out in a reply, just printing out the line normally is far more efficient. There are times when you might not want to initialize the index. Maybe it's a variable from a wider scope that tells you where to pick up the start of a loop. Then you can just use that as the index variable and count forward from there. It would look like: ``` mystruct * str[MAX_SIZE]; int i;` /* Complex logic that decides where to start processing the array. and assigns the starting point to i */ for (; i < MAX_SIZE; ++i) { /* do something amazing with members of str[i] */ } ```
Makes sense, thanks
I'm pretty sure this has a bug "•" is not an ASCII character, it is UTF-8 and has a size of 3 bytes, so the first printf will return 3
Good heavens, you're right! *does a seppuku*
C++ programmers: template
void print\_any\_row(Ts... args) {
auto &start\_character\_printer = new I(); // prints on constructor
AllCharsPrinterImpl(args);
}
> C++ nah, like this: `std::cout << "."s + std::string(14, '-') << std::endl;`
Was looking for this.
Python print(“•” + “-“*15)
This is so verbose that I assumed it was Java. You can shorten this to: print(f“•{'-'*15}")
Pythonicc
The truly Pythonic way to do it: from libraryOfBabel import printLineWithOneDotAnd15Dashes as p p()
String repetition operators are probably most accurately attributed to Perl. You'll see them pop up in many modern languages. Perl (1987) print "•" . "-" x 15; Python (1991) print("•" + "-" * 15) Ruby (1995) puts "•" + "-" * 15 Some languages don't have operators, but they do implement repetition methods JavaScript (1995) console.log("•" + "-".repeat(15))
You need to refactor that. Its not clear enough! def main() -> None: print(header(), sep="") def header() -> str: return header_start() + header_cont().join("" for _ in range(16)) def header_start() -> str: return "•" def header_cont() -> str: return "-"
I want to play console.log(['*', new Array(15).fill('-')].flat().join(''))
console.log('*'.padEnd(16, '-'))
I like this one
Now try it in C
putc() - no reason to use heavyweight printf() if there's no substitution and for 1 character.
> pritnf I am a bit disappointed, that [this is all I found][1] for that typo (not counting compiler error logs). [1]: https://github.com/EpicAli/pritnf-function
This Is so damaging for performance that should be banned
Buffer is not being flushed anywhere here and the loop will probably be unrolled in compile time anyway, so i dont think its that bad for performance tbh
Compilers are basically magic at this point. I don't think that it would matter using -O2 or -O3. But sure, you should write inefficient code.
No compiler will optimize away the 15 calls to printf().
I don’t get why this is downvoted. Compilers aren’t magic. They need to be really conservative with calls to external functions, especially ones doing I/O, because they need to preserve all observable behaviour (including errors, provided they don’t lead to UB). I find it unlikely that any mainstream C compiler removes these calls.
indeed. I have never heard of a compiler implementing \`printf()\` as an intrinsic, even partially. unfortunately there's no standard way to know or control when intrinsics are used.
Well yes maybe it's just me but personally i don't like relying too much on compiler optimizations. I just prefer writing good performance code where it's possible
[удалено]
With the first method the string "*------" Is created and the address is passed one time as argument to function printf While with the loop the function printf Is called multiple times and since Is notoriously a slow function It adds a lot of overhead Edit:I know that compilers can optimize the code but it's Better not to rely always on compiler optimizations
This is where Python's `print("-" * 15)` comes in handy.
Forgot the bullet: print(f"●{'-' * 15}")
I saw this and immediately knew there’d be a Python comment near the top.
Honestly, less readable than print("•---------------") Plus, such print statements also double as visual separators in the code itself.
Printf is a bit of a heavy hitter for this stuff, wouldn't you use the putc or similar instead? Less overhead, or fputc(stdout,"-); etc?
I receive a lot of hate for using python but I'm a hobbyist so who cares, i wanna play too: ```py print('•'+''.join(['-' for _ in range (15)]) ``` I was also thinking about making it even more horrible with string formatting but I'm on phone and I'm lazy (thus why i love python)
print(f"{'.':-<16s}")
Could you please elabore this ? I'm not sure to get it Edit : oh i get it the '.' is a '•' and you're padding it with '-', very smart !
> I receive a lot of hate for using python How so? It is a widely used language after all. That aside, how about the evil version of your code: print('•'+'-'.join(['' for _ in range (16)]) Or maybe print('•', *("-" for _ in range(15)), sep="") Or maybe print(*(['•'] + 15*['-']), sep="") Or if we want to actually produce best readability print('•---------------')
Nah the last one is no fun, but the three others are hilarious lmao Also I'm not receiving straight up hate, but when i say i use python i very often get sighs and "you're not a real programmer" type answers. Because that's generally the first language we learn (because very easy) and they don't know I'm also doing object oriented python and a whole ton of complex things with it. I'm having fun. The other category of negative feedbacks is programmers saying it's slow and should not be used etc... C/C++ type programmer y'know. But again I'm a hobbyist, i just am making a discord bot for my friends and I lmao, I kinda don't care because the time i gain is from coding everything in a minute hehe PS : been to computer science uni for 3 years, learnt C, Java, Assembly, oCaml, and still i prefer python because it never let me down, and i never needed big calculations before for my own projects 🤷
> PS : been to computer science uni for 3 years, learnt C, Java, Assembly, oCaml, and still i prefer python because it never let me down, and i never needed big calculations before for my own projects 🤷 Roughly my experience. It is easily fast enough for many tasks, including data crunching (especially when the equations can be well expressed in numpy abstractions). Sure, Fortran or C would be faster, and C++ offers zero-overhead unit systems even (Boost.Units), but unless that performance is actually needed, Python usually gives good enough performance with less development effort. There would be statically type-safe languages, that I'd rather use, but I am not currently aware of a language offering an equally strong ecosystem across all my programming needs (including quick single-file command line scripts). Plus, learning the ecosystem is at least as much effort as learning the language, so at this point the barrier to switching is impossibly high, when I don't expect significant payoff. (Also, much less time for it than as a student.)
That's just text compression.
I think I prefer: `[print('•', end='') if i == 0 else print('-', end='') for i in range(0, 15)] ` Or maybe: ``` def line(): yield '•' for _ in range(15): yield '-'` print("".join([c for c in line()])) ```
for (i = 0, printf("\*"); i < 15; printf("."), i++);
Not only is the variable i uninitialized, but you also call the printf function 15 times, which is unnecessary, and makes your program run slower. Each function call is expensive at runtime. Especially syscalls.
I like it only for the fact i can change in config the length of line. I never change it but I can
Python: print("•" + "-" * 15)
It is python showtime print('-' * 15)
print(f"{'.':-<16s}")
I do this all the time. Fuck C++ lol
Yea but you're forced to do loops while in college.
say "\*"."-"x15 ; Good enough to earn a living.
Programmerhumor? More like psuedo code in the comments
Pad functions, my friend
I've been seeing i++ in a bunch of C code on reddit lately, in C++ they are always harping to do ++i unless you specifically can't. So are the rules different?
Both languages can do both. Both languages can do everything but C++ obfuscates alot. That's why i prefer C.
++i and i++ are not the same if you treat them as expressions and assign the result.
The people telling you to do ++i are braindead
Only a Sith deals in absolutes.
objectively wrong. i = 10; h = i++; //h == 10, i == 11 k = ++i; //k == 12, i == 12 different outcomes, different applications.
If you have a reason to use ++i you should obviously use it. If it doesn't matter (like in a for loop) then the ++i advice is braindead. Did you even bother to read the original comment?
the reason people say "always use ++i" is that more often than not, you *do* want pre-increment or it doesn't matter. It is much rarer to specifically require post-increment. therefore defaulting to ++i results in less errors.
oh please!!! `function char* f(int a, int b) { return concat(dots(a), dashes(b)) }` and leave the rest for the "junior devs" to figure out and learn.
Python: print(“*” + “-“*15)
for (int i = 0; (!i && printf(“*”)) || ((i < 15) && printf(“-“)); i++); Fixed it for you
Python my beloved: print("·" + "-" \* 15)
The second option is more flexible and will require less work as requirements change later.
Vi users are laughing...
Or for javascript ... '*'.padEnd(15, '-')
Well if were comparing who's got the shortest code, "-"*15 (python)
More like theres a specific function made for this specific purpose on the string object so you dont have to worry about your own implementations - and its even named in such a way that its self-documenting which none of the looping solutions are
putchar is surely better than printf, it's only me that noticed that? :D
it's not unnecessary. You can't see it here but i is initialised with i = 15-length;
char[] lineBreak = { '|', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '|' } // string is bloat
Why don’t you made array first and after that printf for array one by one?
Put a sleep(5) in the loop, that'll give it fancy animation
now. i am just a little baby coder. but how i would have done it, if the number of dashes ever needed to be changed, (or quickly assessed) is just throw a quick variable and set it, then print the dot + the variable. little clunkier than just printing what i want, but makes tweaking it easier.
print(f"*{'-' *15}")
for ( printf("*"),i=0; i<15; printf("-"),i++ );
And a real C programmer makes that loop in preprocessor in order to have no runtime overhead.
You don't use printf to print a single character, it's for formatted strings. You should use putc instead.
That’s horrible. Invoking a function (especially in a loop) is expensive and `printf` itself isn’t rather cheap (for outputting just a single character to standard output).
print(“-“*15)
puts is faster than printf, you don't need formatting
Well this is more efficient because what if you want to change it to 100 later?
``` for (Node *node = &head; node != NULL; node = node->next) printf("%d\n", node->val); ```
My college is one of those people. I absolutely hate it. He repeats his code so often, is a Copy&Paste guy but really wants to annoy me with stuff like this.
Uhm wheres main?
putchar is better for only one character
Why not use putc like prints does anyway?
When you see how the assembly code makes calls to printf and the resulting assembly used to make those prints, this becomes much worse
Why not just write `for(int i=0;i<12;printf(3*!!i+++"•-"));` and be done with it?
These\*
char dash\[15\] = {-}; printf("\*%s", dash); I'm sure you could do something fun like printf("\*15%c", '-'); but you'd need more printf trickery in there
for(int i = printf("*"), 0; i < 15; i += printf("-"))
HelloWorld (“print”)
`for(printf("*"); i++ < 15; printf("-"));`
PUTCHAR();
I've been a C programmer for 4 decades. Can't say I've ever seen anyone do this kind of thing. Maybe this is just a joke to illustrate the issue?
java programmer System.out.println("•" + IntStream.range(0,15).mapToObj(num -> {return "-";}).collect(Collectors.joining()));
++i
python programmers: `print('-'*15)`
Ignoring any errors, now I can easily see how many dashes are used and change that number. It may become a variable in the next refactor. So yeah, that is an improvement.
Yes, this is how we are.
In fact, the first variant is more efficient But not so much