Another thing that's worth saying is you should be careful what code you are committing. Your formatter might change some section of code you are not working on. Either because your formatter has a small difference from someone else's or because it's old code that uses an old format. If you push these changes you may cause unnecessary merge conflicts. It also makes it a little more difficult to git blame a section of code in order to find who an issue needs to be raised to. Don't get blamed for something you didn't write. Keep commits small and check the diff carefully before you commit.
tabs vs spaces is an easy argument because simply, with tabs the programmer can chose a tab width (which is very useful for people with poor eyesight who use huge fonts), while a space width is fixed so it becomes really hard to read with big fonts
Nope, because if you use a fixed pitch font that argument holds no water. If the editor you're using doesn't scale spaces with the rest of the font then it's just wrong.
@@adamm450 No, I'd advocating using tabs for indentation, and space for alignment. Look at 1:37, the indentation is tabs, but making the equal signs align would be done through spaces. This doesn't mean I'm using both tabs and spaces for indentation, this means I'm using tabs for indentation, and only using spaces for alignment and aesthetics.
I once created a .clang-format configuration and put it in my home folder and waste no more time to even think about the correct formatting. Overwriting this configuration is also possible with a .clang-format file located in the project directory. A lot of open source projects do it that way.
Haha! "Anything can be a thing... I hope that's not a thing." Spot on! I'm gonna steal that, because it can be said for soo many things that are a thing but shouldn't be.
Loved this. I do small projects and lots of them. I sometimes spend a lot of the time trying to figure out how to do something. I try to write my code for my future self to save future time. My colleagues also find it helpful when I share. Do a good job formatting and documenting now. Your future self will thank you.
I used to favour curly braces on the line that started the block, like if (cond) { // code } And I think I sort of still do. But I am being won over a little by if (cond) { // code } Well, my real feelings is that if should always have them with it, but functions; I kinda like void func(args) { } but I dunno. That'd also be inconsistent. It's kinda hard
Opening and closing on their own lines so you can visually match them instead of shifting your focus waaaaay to the right to see if an opening brace was used, yep. Also, you don't need braces for single line blocks, and I don't care what any style guide tells me on that front.
@@anon_y_mousse Indeed, I hate to double-check a statement to see if it has or not an opening {. When lines are independent, the block's beginning is rather clear.
1:06, Just to point out something I encountered recently, in certain situations the compiler will treat this particular code as erroneous and refuse to compile, apparantly because the C standard does not explicitly say that void* should be able to cast to a function pointer it is in fact an error to do so, because of that particular error and my slight obsession with making my code compatible with the strictest of situations, I've now taken to using unions to bypass the error, so instead of: sysmalloc = (malloc_like_function)dlsym( RTLD_NEXT, "malloc" ); I use something like: union { void* ptr; malloc_like_function cb; } mallocCBunion; mallocCBunion.ptr = dlsym( RTLD_NEXT, "malloc" ); sysmalloc = mallocCBunion.cb; It's a minor change and guarantees the compiler will not complain at me for casting normal pointer to a function pointer.
The standard ironically defines it as UB, but allows conversion as an extension by the compiler. There are at least two reasons for this, and for most people they'll be on a platform where neither may affect them, at least that is from a functional perspective because there are also other reasons which most can also ignore. Anyhow, pointer size mismatches, which you mostly avoid with a union, assuming the platform you're on doesn't play any shenanigans with how they address functions and data, and of course systems that lock code sections and prevent them from being written to with data. Most don't have to worry about that, and truthfully it's a pointless distinction because if you can modify a program that's stored on disk you can run whatever you want anyway.
I think void** might be a resolution to this instead. I've seen this especially in the Windows API and some production code. I'm just having a rough time with it because I haven't touched pointer to function casts in a hot minute 😅
@@v01d_r34l1ty One problem here are Harvard architectures. A pointer to function may be larger than a void*, so you have to handle them differently. Edit: premature post
@@v01d_r34l1ty A Harvard architecture has a separate address space for code and data. For an example you may look at the Atmel (now Microchip) SOCs used by makers e.g. on the Arduino platform. There are special instructions to read from code space, like for initialized data, e.g. strings.
Clicking the thumbnail my thought was please mention "tabs to indent, spaces to align". I was sure you would, but alas, you have to make another video now. :)
Yesh, my comment is 'Please do something to make your audio louder' :) Please :) It isn't just you. I watch other folks that have low audio while other guys have vids that 'scream' at me when they come on. Though those guys are 'YT professionals' in the sense that they make a living doing YT.
@@xenobino8432 I know it that moment it felt very difficult, but in the long run it will have been one step closer to reaching full coder nivana. My coder ego is gone so there is no need thanking me, just spread this caring practise to other, less enlighted coders. 🌞
Always something new to learn jacob, showed this video to my co-worker at the time of review . We usually use vim and has auto indent option which we use got to know about indent command today.
The most important thing with formatting is _not_ consistency. Things can be consistently bad, or consistently wrong. The most important thing is the silhouette of the code. We spend a lot more time reading code than writing it.
One of the first things I do when setting up a C project is copying the clangformat file from the linux kernel. It’s a bit of a pain if you have vendor code that you need to edit though.
When I was learning to code I tried to learn indentation rules 😂 Noobie mistake on my part. Then I started to work and it turned out that everything I learned didn't matter as the company I work for has its own code formatting rules and we all must use the same clang-format. Every company (with good programming practices) will have its own code formatting rules, so just use what they tell you, they won't allow you otherwise anyway.
Tabs for indentation, space for alignment. Example at 1:37 - Tabs for indentation and then spaces to make the equal signs align. This has the simple effect that alignment is respected and _always_ works. And if people are used to a different indentation width, their editor can trivially support it without converting anything. The argument that "but if I use tabs, then the code won't show up exactly the same way on other's screen" is a silly argument. Yeah, it might not, because other people may prefer a higher or lower indentation width. This is a total non-issue. People's preferences should be respected, and using spaces don't respect anything without the editor having to convert it, and that _does_ fail sometimes. If you're worried about alignment, then use spaces for alignment after tab indentation. Doing this prevents having to use tools or have editors auto-convert indentation method, and I've seen when it goes wrong... And oh dear, is it _not_ fun to manually fix it when it does go wrong! This also prevents the dreaded pull requests on git where the diff is absolutely useless because every line changed because their editor decided to change the indentation method. Yeah, the editor _could_ reformat it to the correct format, but it can fail too, and is also just unnecessary work when there is a way simpler solution (this solution). What I am describing here, is _objectively_ superior because: 1. Individual preferences to indent width is respected. 2. Alignment where it is used, is respected. 3. Editors don't need to be overly complicated or do unnecessary work. 4. This avoids when editors convert indentation incorrectly, causing more mess. 5. Saves a few thousand bytes off your... 1TB...... compu...ter..... Yeah scrap this point... As for coding style, there's mostly not an objective better style. There are some things that might be better than others, but by large, it's preference.
I once had a project with tabs instead of spaces. All your points applied there. Then I committed my code, pushed it to GitLab and looked at the merge request. There I saw that GitLab uses a tab width of 8 spaces. The code looked just horrifying and I have not found any way to change that back then.
@@whaisonw2865 I'm not entirely sure what you mean, but sounds like they are just displaying tabs as spaces, but not actually changing the tabs to spaces.
@@xDahl Yeah, no it didn't change the code. It was just displaying it this way in GitLab. I did not find the setting for changing that in the browser. It is just different in my editor so I always got annoyed by that when I looked into merge requests.
There are very few things that are objectively true about code style, but this is one of them. Regardless of whether you indent with tabs or spaces, aligning continued lines should always, always be done with spaces only. It fixes all the complaints that the space indentation crowd mistakenly thinks are caused by tab indentation.
If many developers are working on the project, to avoid mixing Tabs and Spaces, You can use .editorconfig (most text editors and IDE has a plugin for it), which makes life much more easier. .editorconfig example root = true [*] charset = utf-8 end_of_line = lf insert_final_newline = true indent_style = space indent_size = 2 trim_trailing_whitespace = true [Makefile] indent_style = tab
@@Spiderboydk That I think is the best reason to do that. You'll always find the start or end bracket easier if it's on the same column. I don't do it like that personally tho as I like less rows for some reason :)
So, for projects where CamelCase is preferred: they can use reverse camel case for constants. Its genius and I like the idea. (Personally I prefer underscores.)
Just got to wait for a language author to be brave enough to make improper formatting a compile error. I remember hard tab characters causing compile errors in Zig, bit I think that was a limitation of the implementation that the creator span as a feature.
Indent is a useful program, though I've never used it myself. If I reformat someone else's code prior to editing it, I'll do so by hand so I can read their code fully. My own personal style, which doesn't seem to be fully shared by anyone is, 2 spaces to indent each level, my tab key inserts 4 spaces for brevity's sake, braces get their own line, spaces left and right around parens except around the open paren of a function *call*, but not definition where it still gets a space, no space between the first paren of a macro definition and the macro name, but only due to language requirements, spaces internal to brackets, an extra newline after a trailing brace unless it's followed by an outer scope's trailing brace or it's the last in the file. I also put a space between the primary type of a pointer and the asterisk and rather than formatting variable declarations and assignments so that the = match up and everything is centered on that, I rearrange them by length to form triangles, growing towards a block and shrinking away from it, and I even try to name my variables to facilitate this OCD.
I liked a lot of what you are saying; except I've never used macros beyond include guards; lining up variable declarations to form a triangle is some awesome OCD 👍🏻😁. Although I'm surprised that you need to define so many variables in one place that it's possible to do it. I started programming in C in 2001, and then switched to C++, before that I had been using FORTRAN and PASCAL, and so used to define all my variables at the beginning of the program. I can't remember if I ordered them in alphabetical order or in order of use. But after a pause of about 10 years I'm back doing some C++ programming and have decided to let the compiler do the optimising and so declare variables only where they are used, even if it's a temporary variable inside a loop, I'm trusting that the compiler is smart enough to know the variable can be created outside the loop, so I don't have to worry about a variable beginning declared 20 lines away from where it's used, and it reduces the variable's scope.
In Go we use giftmt which lexes and parses then rewrites the source in the format that giftmt likes. It's like the first thing that runs in any IDE tooling or any tool that modifies the code (giftmt is in the library, not just a tool). So almost every project will always be formated the way giftmt formats it. The proverb is "giftmt is nobody's favorite format, but giftmt is everybody's favorite". We don't argue about any conventions. Just gofmt.
I myself still don't know where should the braces go, and I end up having multiple styles in the same project. And another thing is if the '*' should go right before the variable name or next to the type.
As to "the other thing", I recommend thinking about declaring 2 ptrs at once: char *p1, *p2; The variables are, first and foremost, "pointers". The datatype that they point at is secondary. char* ptr; // Just plain wrong!!! Let the flaming begin... As to "wherefore art thou, Braces?", an iterator scanning linked list of ptrs for a record: for( p = pHead; p && !match( p, target ); p = p->next ) { } // search list to find target or NULL The entire iterator loop can be on one line. Some idiots aren't comfortable with more than one idiom... 🙂
Formatters can expose some logical errors, for example: while (conditiioncheck); { doSomethigHere(); } after code format its easier to spot an empty statement in a while loop: while (condition) ; { doSomethingHere(); }
I strictly follow my personal indentation style in C. Some of the guidelines go as follows: I - Always try to avoid inline declaration of multiple variables if the total length of the line exceeds 24 characters, including tabulation. II - Always declare variables with type modifiers with their intended type, unless the total line length exceeds 24 characters. unsigned long long int instead of unsigned long long, and the like. III - Function call parentheses mustn't have a space after the function's name. IV - Whenever possible, curly braces should be on the line below of the function, loop or conditional statement in question, aligned with the first character of the function, loop or conditional's name. V - Whatever is inside curly braces should be on a new line, with a tabulation character added in relation to the previous scope. VI - Always involve a conditional expression in parentheses without a space padding if they are being logically compared with others. (a > b) && (c < d) instead of a > b && c < d. VII - Always insert a space in between operands unless the operation is the logical negator or dereference operator. (c >= 'a') && (i ='a')&&(i
Over in PHP world... we actually have defined standards for this sorta thing (I think the Python crowd do too). When I first stated using PSR-12 I hated it "How dare some 'overlord' tell me how many spaces to indent?"... But once I got used to it it was fabulous, "look the whole PHP community are united with one indentation style to rule them all"... Now I've moved to a job where we have a completely different set of rules and nobody sticks to them anyway it's like going back to the dark-ages.... Now, if all the "curly brace languages" could get together an specify a cross-language style.... that would be NIRVANA!
Throwing in a new comment after mentioning the topic of indenting vs aligning in a previous one. I believe it warrants a short video as it's an underappreciated detail. The core of the matter is tab width, and how it relates to the maxim of not mixing tabs and spaces. A test: open a file that uses tab indentation. Change a line or two to be space-indented. Disable any whitespace visualization markers. You won't notice the incorrect indentation (which is why mixing tabs vs. spaces happens to begin with). Now change your editor's tab width setting. This is what your hypothetical coworker sees because you assumed that a tab is N characters wide universally. Ok, everything so far is basic stuff. Next test: open tab-indented file with long lines. Break long lines into multiple with manual newlines (e.g. at < 80 characters). Use tabs to indent the continuation lines, and then also align them with tab. Then change your tab width. In my opinion there's an objectively correct way to use tabs and spaces in tab-indented code: indent with tabs, then align continued lines with space so that the spaces start at the current indentation level. This is the *only* way that does not rely on a specific tab width setting to make the alignment look correct. So, if you indent with tabs, *never* align with tabs! (Btw, the Linux kernel uses tabs for alignment and will only look right with a tab width of 8. It's their choice, and I use 8 tab width myself, but I still dislike this specific detail about kernel code.)
The only reason I put the starting curly bracket together with the round brackets is to save an extra line in the file......and because my company's coding standard encourages to do so too
@@sababugs1125 lol :-D In all seriousness, I actually don't care that much whether it's left or right as long as it's consistent throughout the project.
@@Spiderboydk ditto on that. If only we could have code as a database so we wouldn't fuss over these small things like indentation or curly braces... 😈
Formatting is nice and all for humans, but due to the "free-form" nature of C (with the exception all statements end in ';'), it has spawned the ever-so-awesome IOCCC (International Obfuscated C Code Contest). It's basically a contest to see who can make the ugliest, most unreadable code that still compiles and runs -- essentially the opposite of the good tips explained in this video :). I couldn't find a specific site for everything, but a quick search came up with a bunch of places with examples of some of the winners.
On a tangent but… Can I get a movement started where college and university courses that require code to be present in papers PLEASE change their required writing formats to allow monospaced fonts to be used for programs? This turns beautiful pieces of code ugly on the printed page for no good reason.
"Why we would be so naive as to think we could all, like the whole world full of programmers, would all be able to agree on something like this and come up with some standard code format? Yeah, no, not a chance." Meanwhile all of Rust users are using the rustfmt…
@@anon_y_mousse That's funny take. But I would argue that it is because it is well designed language. By people that know that details like this matter.
@@aleksanderkrauze9304 They don't as a matter of fact. It's all personal taste. However, the details that do matter, they get wrong most of the time. It's not the only language that does this, it's just the newest. I wish I could say it will disappear in 6 months, but Python has proven that the worst languages can stay alive as long as enough mental patients use it.
@@anon_y_mousse That comment left me wandering who here is mental. There are no wright and wrong design choices. There are only tools that are better or worse at particular job. Maybe you don't need a language like Python or Rust, but many people do.
@@aleksanderkrauze9304 If the design choice intentionally hinders developers then the choice is wrong. Python has quite a few of those, Rust fewer, but still has them.
How to Indent Code the Right Way? Use the formatter or indentation specification provided the language you are using. The language has no standard? Get ready for endless debates :]
80 chars comes from a monitor constraint that is from the jurassic age, so while it makes sense to limit line width to something sensible, 80 or so chars today is silly.
@@fixfaxerify Well, that what I felt when I encountered Python, with all the identing requirements - it was like return to punch cards to me. Back in 80-s when I started programming 'free form' was all the rage.
If you want a certain code format (and don't write python) then use a damn formatter. If this video doesn't talk about that I'd consider it a waste of time. Usually there is an argument for a lot of ways of doing things, as long as they're consistent, I don't believe there is one true style besides the one that most people can read good enough, or your personal preference if the code is for your consumption alone. Edit: Yeah, well, basically the same speaking points, good.
One of my biggest complaints about code formatters is that they cannot recognize similar blocks of code and format them in the same way. For example, I wrote a series of calls to a (C++ template) function to create several subscribers. In each call I put the longest argument, the topic name, on its own line so it would be easy to spot, and grouped the other, shorter arguments on one line. The formatter packed as many arguments as it could fit into each line, breaking lines between different arguments. I’ve had similar experiences with cases in switch statements, and with getter and setter functions. I like to use aligned braces most of the time because they create vertical white space that separates function headers from bodies, and if, while, and for statements from their subordinate statements. But I’ll switch to Egyptian braces on the innermost blocks to show they’re tightly bound fragments. Formatters make you choose one style of bracing for all the code. I think code formatters are very useful, and make code look about 90% the way I want it to look. But I always have to clean up some places by hand after them.
2:06 "Lowercase with underscores" I've often heard described as lower_snake_case. There's also Upper_Snake_Case, and SCREAMING_SNAKE_CASE
SCREAMING_SNAKE_CASE mostly for macro because it screams that it's not a real function
@@KangJangkrik and also snakes are know to be tricky
@@user-sl6gn1ss8p correct. Especially when you missed semicolon next to macro (try it lol)
When I'm contributing to open source projects, it's not my choice anyway. I have to stick to their standards no matter how much I hate it.
Use an auto formatting tool
@@thedoublehelix5661 ah, yes, looking through a pull request with 1000+ lines changed because whitespaces. Nice indeed
Have it auto format when you pull it to your local machine how you like; then have it format how they want it when you push
If there is a really good reason for it, you can always //clang-format off for a second. Have fun arguing why it's necessary, though.
Another thing that's worth saying is you should be careful what code you are committing. Your formatter might change some section of code you are not working on. Either because your formatter has a small difference from someone else's or because it's old code that uses an old format. If you push these changes you may cause unnecessary merge conflicts. It also makes it a little more difficult to git blame a section of code in order to find who an issue needs to be raised to. Don't get blamed for something you didn't write. Keep commits small and check the diff carefully before you commit.
Agree, important to realise that reformatting a file will ensure that your fix gets buried in an avalanche of differences.
Over in the Python world, they've got a solution to this. They use a formatted called "Black" which has NO SETTINGS.
@@edgeeffect Definitely. Similar to gofmt in golang world.
tabs vs spaces is an easy argument because simply, with tabs the programmer can chose a tab width (which is very useful for people with poor eyesight who use huge fonts), while a space width is fixed so it becomes really hard to read with big fonts
spaces allow for aligning code precisely, tabs dont allow this because of variable tab size. its an endless debate, both have pros and cons
Nope, because if you use a fixed pitch font that argument holds no water. If the editor you're using doesn't scale spaces with the rest of the font then it's just wrong.
@@adamm450 Use space for alignment, tabs for indentation. Problem solved.
@@xDahl then you are not really using either tabs or spaces, but both
@@adamm450 No, I'd advocating using tabs for indentation, and space for alignment. Look at 1:37, the indentation is tabs, but making the equal signs align would be done through spaces. This doesn't mean I'm using both tabs and spaces for indentation, this means I'm using tabs for indentation, and only using spaces for alignment and aesthetics.
I once created a .clang-format configuration and put it in my home folder and waste no more time to even think about the correct formatting.
Overwriting this configuration is also possible with a .clang-format file located in the project directory. A lot of open source projects do it that way.
Very helpful info!!
Haha! "Anything can be a thing... I hope that's not a thing." Spot on! I'm gonna steal that, because it can be said for soo many things that are a thing but shouldn't be.
Loved this. I do small projects and lots of them. I sometimes spend a lot of the time trying to figure out how to do something. I try to write my code for my future self to save future time. My colleagues also find it helpful when I share. Do a good job formatting and documenting now. Your future self will thank you.
4:08 I like how the comment still says "this is an [...] example of how not to format your code".
I told ya, the curly brace belongs on the same line!
😂
I used to favour curly braces on the line that started the block, like
if (cond) {
// code
}
And I think I sort of still do. But I am being won over a little by
if (cond)
{
// code
}
Well, my real feelings is that if should always have them with it, but functions; I kinda like
void func(args)
{
}
but I dunno. That'd also be inconsistent. It's kinda hard
putting curly brace on separate lines makes the commit history more readable
Opening and closing on their own lines so you can visually match them instead of shifting your focus waaaaay to the right to see if an opening brace was used, yep. Also, you don't need braces for single line blocks, and I don't care what any style guide tells me on that front.
@@anon_y_mousse Even better is to make liberal use of commas instead of semicolons and reduce the need for curly braces... 🙂
@@rustycherkas8229 I'm assuming that's sarcasm, because it's a much better idea, both visually and functionally to not write your code that way.
@@anon_y_mousse Indeed, I hate to double-check a statement to see if it has or not an opening {. When lines are independent, the block's beginning is rather clear.
1:06, Just to point out something I encountered recently, in certain situations the compiler will treat this particular code as erroneous and refuse to compile, apparantly because the C standard does not explicitly say that void* should be able to cast to a function pointer it is in fact an error to do so, because of that particular error and my slight obsession with making my code compatible with the strictest of situations, I've now taken to using unions to bypass the error, so instead of:
sysmalloc = (malloc_like_function)dlsym( RTLD_NEXT, "malloc" );
I use something like:
union { void* ptr; malloc_like_function cb; } mallocCBunion;
mallocCBunion.ptr = dlsym( RTLD_NEXT, "malloc" );
sysmalloc = mallocCBunion.cb;
It's a minor change and guarantees the compiler will not complain at me for casting normal pointer to a function pointer.
The standard ironically defines it as UB, but allows conversion as an extension by the compiler. There are at least two reasons for this, and for most people they'll be on a platform where neither may affect them, at least that is from a functional perspective because there are also other reasons which most can also ignore. Anyhow, pointer size mismatches, which you mostly avoid with a union, assuming the platform you're on doesn't play any shenanigans with how they address functions and data, and of course systems that lock code sections and prevent them from being written to with data. Most don't have to worry about that, and truthfully it's a pointless distinction because if you can modify a program that's stored on disk you can run whatever you want anyway.
I think void** might be a resolution to this instead. I've seen this especially in the Windows API and some production code. I'm just having a rough time with it because I haven't touched pointer to function casts in a hot minute 😅
@@v01d_r34l1ty One problem here are Harvard architectures. A pointer to function may be larger than a void*, so you have to handle them differently.
Edit: premature post
@@Hauketal Don’t know what those are or why that would be the case but I’ll take your word for it lol
@@v01d_r34l1ty A Harvard architecture has a separate address space for code and data. For an example you may look at the Atmel (now Microchip) SOCs used by makers e.g. on the Arduino platform.
There are special instructions to read from code space, like for initialized data, e.g. strings.
Thanks Jacob.
Are you aware of any instance where a formatter introduced some bug(s)?
Clicking the thumbnail my thought was please mention "tabs to indent, spaces to align". I was sure you would, but alas, you have to make another video now. :)
Yesh, my comment is 'Please do something to make your audio louder' :)
Please :)
It isn't just you. I watch other folks that have low audio while other guys have vids that 'scream' at me when they come on. Though those guys are 'YT professionals' in the sense that they make a living doing YT.
I alway commit code where every line is indented by one space per line of code. It is to help my collegues to practice their anger management skills.
Congrats. You just made a man go angry over a comment at 1:43am.
@@xenobino8432 I know it that moment it felt very difficult, but in the long run it will have been one step closer to reaching full coder nivana. My coder ego is gone so there is no need thanking me, just spread this caring practise to other, less enlighted coders. 🌞
Yes officer this comment right here
Found the guy who wrote Windows Me
Wow! Never knew about _indent_ . Thank you!
Always something new to learn jacob, showed this video to my co-worker at the time of review . We usually use vim and has auto indent option which we use got to know about indent command today.
I usually do a space, a tab then 2 more spaces for ease of use.
ah yes of course. the good ol' "space tab 2 space" indentation style
The most important thing with formatting is _not_ consistency. Things can be consistently bad, or consistently wrong. The most important thing is the silhouette of the code. We spend a lot more time reading code than writing it.
well if youre consistently bad, eventually those seeing your code such as co workers would learn to read it lol
Your videos are just extremely helpfull. I have learned so much from them, thank you👍🏽!
Thanks. Glad you like them.
One of the first things I do when setting up a C project is copying the clangformat file from the linux kernel. It’s a bit of a pain if you have vendor code that you need to edit though.
Formatting standard is pretty clear, how about directory structure like The Pitchfork Convention?
When I was learning to code I tried to learn indentation rules 😂 Noobie mistake on my part. Then I started to work and it turned out that everything I learned didn't matter as the company I work for has its own code formatting rules and we all must use the same clang-format. Every company (with good programming practices) will have its own code formatting rules, so just use what they tell you, they won't allow you otherwise anyway.
Tabs for indentation, space for alignment.
Example at 1:37 - Tabs for indentation and then spaces to make the equal signs align.
This has the simple effect that alignment is respected and _always_ works.
And if people are used to a different indentation width, their editor can trivially support it without converting anything.
The argument that "but if I use tabs, then the code won't show up exactly the same way on other's screen" is a silly argument.
Yeah, it might not, because other people may prefer a higher or lower indentation width. This is a total non-issue. People's preferences should be respected, and using spaces don't respect anything without the editor having to convert it, and that _does_ fail sometimes.
If you're worried about alignment, then use spaces for alignment after tab indentation.
Doing this prevents having to use tools or have editors auto-convert indentation method, and I've seen when it goes wrong... And oh dear, is it _not_ fun to manually fix it when it does go wrong!
This also prevents the dreaded pull requests on git where the diff is absolutely useless because every line changed because their editor decided to change the indentation method. Yeah, the editor _could_ reformat it to the correct format, but it can fail too, and is also just unnecessary work when there is a way simpler solution (this solution).
What I am describing here, is _objectively_ superior because:
1. Individual preferences to indent width is respected.
2. Alignment where it is used, is respected.
3. Editors don't need to be overly complicated or do unnecessary work.
4. This avoids when editors convert indentation incorrectly, causing more mess.
5. Saves a few thousand bytes off your... 1TB...... compu...ter..... Yeah scrap this point...
As for coding style, there's mostly not an objective better style.
There are some things that might be better than others, but by large, it's preference.
I once had a project with tabs instead of spaces. All your points applied there. Then I committed my code, pushed it to GitLab and looked at the merge request. There I saw that GitLab uses a tab width of 8 spaces. The code looked just horrifying and I have not found any way to change that back then.
@@whaisonw2865 I'm not entirely sure what you mean, but sounds like they are just displaying tabs as spaces, but not actually changing the tabs to spaces.
@@xDahl Yeah, no it didn't change the code. It was just displaying it this way in GitLab. I did not find the setting for changing that in the browser. It is just different in my editor so I always got annoyed by that when I looked into merge requests.
There are very few things that are objectively true about code style, but this is one of them. Regardless of whether you indent with tabs or spaces, aligning continued lines should always, always be done with spaces only. It fixes all the complaints that the space indentation crowd mistakenly thinks are caused by tab indentation.
If many developers are working on the project, to avoid mixing Tabs and Spaces, You can use .editorconfig (most text editors and IDE has a plugin for it), which makes life much more easier.
.editorconfig example
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
[Makefile]
indent_style = tab
In 0:30 right is the best way imo
People who put opening braces on a new line when they get carpal tunnel (they've been hitting enter too much) :😭
I like the symmetry of matching brackets being in the same column.
Agreed. Some old school people are afraid of being more up to date. The Allman style makes things clearer.
@@Spiderboydk That I think is the best reason to do that. You'll always find the start or end bracket easier if it's on the same column. I don't do it like that personally tho as I like less rows for some reason :)
So, for projects where CamelCase is preferred: they can use reverse camel case for constants.
Its genius and I like the idea.
(Personally I prefer underscores.)
Just got to wait for a language author to be brave enough to make improper formatting a compile error.
I remember hard tab characters causing compile errors in Zig, bit I think that was a limitation of the implementation that the creator span as a feature.
you mean python?
There are actually several bad languages that do. I consider that thinking which led to their design to be programmer error.
That's why python is a no go for me :). I had enough fun with make early on.
Indent is a useful program, though I've never used it myself. If I reformat someone else's code prior to editing it, I'll do so by hand so I can read their code fully. My own personal style, which doesn't seem to be fully shared by anyone is, 2 spaces to indent each level, my tab key inserts 4 spaces for brevity's sake, braces get their own line, spaces left and right around parens except around the open paren of a function *call*, but not definition where it still gets a space, no space between the first paren of a macro definition and the macro name, but only due to language requirements, spaces internal to brackets, an extra newline after a trailing brace unless it's followed by an outer scope's trailing brace or it's the last in the file. I also put a space between the primary type of a pointer and the asterisk and rather than formatting variable declarations and assignments so that the = match up and everything is centered on that, I rearrange them by length to form triangles, growing towards a block and shrinking away from it, and I even try to name my variables to facilitate this OCD.
I liked a lot of what you are saying; except I've never used macros beyond include guards; lining up variable declarations to form a triangle is some awesome OCD 👍🏻😁. Although I'm surprised that you need to define so many variables in one place that it's possible to do it. I started programming in C in 2001, and then switched to C++, before that I had been using FORTRAN and PASCAL, and so used to define all my variables at the beginning of the program. I can't remember if I ordered them in alphabetical order or in order of use. But after a pause of about 10 years I'm back doing some C++ programming and have decided to let the compiler do the optimising and so declare variables only where they are used, even if it's a temporary variable inside a loop, I'm trusting that the compiler is smart enough to know the variable can be created outside the loop, so I don't have to worry about a variable beginning declared 20 lines away from where it's used, and it reduces the variable's scope.
In Go we use giftmt which lexes and parses then rewrites the source in the format that giftmt likes. It's like the first thing that runs in any IDE tooling or any tool that modifies the code (giftmt is in the library, not just a tool). So almost every project will always be formated the way giftmt formats it. The proverb is "giftmt is nobody's favorite format, but giftmt is everybody's favorite". We don't argue about any conventions. Just gofmt.
I myself still don't know where should the braces go, and I end up having multiple styles in the same project. And another thing is if the '*' should go right before the variable name or next to the type.
As to "the other thing", I recommend thinking about declaring 2 ptrs at once:
char *p1, *p2;
The variables are, first and foremost, "pointers".
The datatype that they point at is secondary.
char* ptr; // Just plain wrong!!!
Let the flaming begin...
As to "wherefore art thou, Braces?", an iterator scanning linked list of ptrs for a record:
for( p = pHead; p && !match( p, target ); p = p->next ) { } // search list to find target or NULL
The entire iterator loop can be on one line.
Some idiots aren't comfortable with more than one idiom... 🙂
in my opinion, declaring multiple variables at once - especially pointers - is ugly in itself
Formatters can expose some logical errors, for example:
while (conditiioncheck); {
doSomethigHere();
}
after code format its easier to spot an empty statement in a while loop:
while (condition)
;
{
doSomethingHere();
}
I strictly follow my personal indentation style in C. Some of the guidelines go as follows:
I - Always try to avoid inline declaration of multiple variables if the total length of the line exceeds 24 characters, including tabulation.
II - Always declare variables with type modifiers with their intended type, unless the total line length exceeds 24 characters. unsigned long long int instead of unsigned long long, and the like.
III - Function call parentheses mustn't have a space after the function's name.
IV - Whenever possible, curly braces should be on the line below of the function, loop or conditional statement in question, aligned with the first character of the function, loop or conditional's name.
V - Whatever is inside curly braces should be on a new line, with a tabulation character added in relation to the previous scope.
VI - Always involve a conditional expression in parentheses without a space padding if they are being logically compared with others. (a > b) && (c < d) instead of a > b && c < d.
VII - Always insert a space in between operands unless the operation is the logical negator or dereference operator. (c >= 'a') && (i ='a')&&(i
Here's a somewhat related style that, imho, greatly improves legibility:
printf( "Hello world
" );
for( init; cond; incr ) ...
if( cond1 && !( cond2 || cond3 ) ) ...
When things get intricate, whitespace around parameter lists really helps ( again 'imo' ).
God, for a while, I thought that my jumpcut counter has turned into a geiger counter.
I will try these tools on the "obfuscated C code contest" codes 🤣🤣
Over in PHP world... we actually have defined standards for this sorta thing (I think the Python crowd do too). When I first stated using PSR-12 I hated it "How dare some 'overlord' tell me how many spaces to indent?"... But once I got used to it it was fabulous, "look the whole PHP community are united with one indentation style to rule them all"... Now I've moved to a job where we have a completely different set of rules and nobody sticks to them anyway it's like going back to the dark-ages....
Now, if all the "curly brace languages" could get together an specify a cross-language style.... that would be NIRVANA!
You do realize that the quotation you’re paraphrasing was originally written by an incredibly evil villain.
@@richardblain4783 this is all an evil plan to eliminate the superior
if (…) [ insert the one
you like more ]
}
Throwing in a new comment after mentioning the topic of indenting vs aligning in a previous one. I believe it warrants a short video as it's an underappreciated detail. The core of the matter is tab width, and how it relates to the maxim of not mixing tabs and spaces.
A test: open a file that uses tab indentation. Change a line or two to be space-indented. Disable any whitespace visualization markers. You won't notice the incorrect indentation (which is why mixing tabs vs. spaces happens to begin with). Now change your editor's tab width setting. This is what your hypothetical coworker sees because you assumed that a tab is N characters wide universally.
Ok, everything so far is basic stuff. Next test: open tab-indented file with long lines. Break long lines into multiple with manual newlines (e.g. at < 80 characters). Use tabs to indent the continuation lines, and then also align them with tab. Then change your tab width.
In my opinion there's an objectively correct way to use tabs and spaces in tab-indented code: indent with tabs, then align continued lines with space so that the spaces start at the current indentation level. This is the *only* way that does not rely on a specific tab width setting to make the alignment look correct. So, if you indent with tabs, *never* align with tabs!
(Btw, the Linux kernel uses tabs for alignment and will only look right with a tab width of 8. It's their choice, and I use 8 tab width myself, but I still dislike this specific detail about kernel code.)
The only reason I put the starting curly bracket together with the round brackets is to save an extra line in the file......and because my company's coding standard encourages to do so too
0:30 left is correct .
I used to think so too, but then I became wiser. ;-)
@@Spiderboydk as we age more of our neurones die and we loose the ability to critically think
@@sababugs1125 lol :-D
In all seriousness, I actually don't care that much whether it's left or right as long as it's consistent throughout the project.
@@Spiderboydk ditto on that. If only we could have code as a database so we wouldn't fuss over these small things like indentation or curly braces... 😈
Of course the right one is the clearer style. So much better for the readability.
Formatting is nice and all for humans, but due to the "free-form" nature of C (with the exception all statements end in ';'), it has spawned the ever-so-awesome IOCCC (International Obfuscated C Code Contest). It's basically a contest to see who can make the ugliest, most unreadable code that still compiles and runs -- essentially the opposite of the good tips explained in this video :). I couldn't find a specific site for everything, but a quick search came up with a bunch of places with examples of some of the winners.
On a tangent but…
Can I get a movement started where college and university courses that require code to be present in papers PLEASE change their required writing formats to allow monospaced fonts to be used for programs?
This turns beautiful pieces of code ugly on the printed page for no good reason.
How to Indent Code the Right Way?
Here's my suggestion:
1. Use tabs over spaces.
1:30 ouch. First indentation has 2 spaces. The next one has 3... Who uses even 3 spaces?
I use 3 spaces of indentation for (and only for!) markdown.
"Why we would be so naive as to think we could all, like the whole world full of programmers, would all be able to agree on something like this and come up with some standard code format? Yeah, no, not a chance." Meanwhile all of Rust users are using the rustfmt…
That's because Rust is mental cancer. It grows until it devours its host.
@@anon_y_mousse That's funny take. But I would argue that it is because it is well designed language. By people that know that details like this matter.
@@aleksanderkrauze9304 They don't as a matter of fact. It's all personal taste. However, the details that do matter, they get wrong most of the time. It's not the only language that does this, it's just the newest. I wish I could say it will disappear in 6 months, but Python has proven that the worst languages can stay alive as long as enough mental patients use it.
@@anon_y_mousse That comment left me wandering who here is mental. There are no wright and wrong design choices. There are only tools that are better or worse at particular job. Maybe you don't need a language like Python or Rust, but many people do.
@@aleksanderkrauze9304 If the design choice intentionally hinders developers then the choice is wrong. Python has quite a few of those, Rust fewer, but still has them.
"or in ten minutes" Too true.
(0:30)
if (...) {
} all the way
0:26 the one on the left
How to Indent Code the Right Way? Use the formatter or indentation specification provided the language you are using.
The language has no standard? Get ready for endless debates :]
On the right!!!!!!
80 chars comes from a monitor constraint that is from the jurassic age, so while it makes sense to limit line width to something sensible, 80 or so chars today is silly.
Not monitor constraint, more like punch card constraint
@@dmitripogosian5084 OK even more silly then, to follow a convention from frickin 1928 😄
@@fixfaxerify Well, that what I felt when I encountered Python, with all the identing requirements - it was like return to punch cards to me. Back in 80-s when I started programming 'free form' was all the rage.
I really hate functions formatted like:
int
functionname(args)
{
More important than how is do it the same way every time.!!!!
I am not sure I learnt anything today apart from: everybody is different ;-)
If you want a certain code format (and don't write python) then use a damn formatter.
If this video doesn't talk about that I'd consider it a waste of time. Usually there is an argument for a lot of ways of doing things, as long as they're consistent, I don't believe there is one true style besides the one that most people can read good enough, or your personal preference if the code is for your consumption alone.
Edit: Yeah, well, basically the same speaking points, good.
Writing a code you should concentrate on the code, not on the way you’ll kill your colleague
Nested ternary conditions in one line 😈
int const
how about letting the formatter take care of everything
It is NOT the RIGHT way, it is A way. That from50 years writing inC
SEMI-COLONS go half-way up.....the.....function
for the algorithm
IT SHOULD BE LIKE THIS
IF()
{
}
It's time to spread the gospel of rEVERSEcAMELcASE!
rust btw
cargo fmt
Uncrustify!!!! It is THE formater.
python fans will jump in your support (although they are sCaReD by C)
Why would fans of a language written in C, embeddable in C, and extendable by C be afraid of C?
was talking about beginners and people that hate pointers
too much introduction, get to the point bro :)
One of my biggest complaints about code formatters is that they cannot recognize similar blocks of code and format them in the same way. For example, I wrote a series of calls to a (C++ template) function to create several subscribers. In each call I put the longest argument, the topic name, on its own line so it would be easy to spot, and grouped the other, shorter arguments on one line. The formatter packed as many arguments as it could fit into each line, breaking lines between different arguments. I’ve had similar experiences with cases in switch statements, and with getter and setter functions.
I like to use aligned braces most of the time because they create vertical white space that separates function headers from bodies, and if, while, and for statements from their subordinate statements. But I’ll switch to Egyptian braces on the innermost blocks to show they’re tightly bound fragments. Formatters make you choose one style of bracing for all the code.
I think code formatters are very useful, and make code look about 90% the way I want it to look. But I always have to clean up some places by hand after them.