@@justcurious1940 I've not learned much on this channel. I like to watch Jacob teaching, what's his approach, where he stops in the complexity, this sort of things.
As for the value of these videos, I'd say the gain I get is tangential as the more people that learn from you the better the industry gets. On the subject of not needing for loops, C gives us many ways to do things, it is only our desires which push us in a given direction. We could after all use labels, gotos and simple ifs. That might make for a really good video to show how looping constructs break down at a low level. Maybe even demonstrate one of my favorite ways of handling cascading errors.
Hi, First of all, great video great content. I have learned a lot from the video series. One thing that I want to add to the explanation is, It's perfectly right to use a while loop for everything but one difference is that my professor told me back when I was in university. If some problem requires a fixed number of iterations or you could say if you know how many times the loop is going to run then use FOR loop and if you don't know the number of iterations like you are reading from a file and the condition is read till ' ' then use While loops. I think this makes sense and it makes sometimes the implementation easy.
I missed for loops iterating over lists in the video, here is the for loop I always write: NODE* head = ...; for(NODE* i = head; i != NULL; i = i->next) { ... } or simply for(NODE* i = head; i; i = i->next) { ... } or if there would have been a '->=' operator in C: for(NODE* i = head; i; i->=next) { ... }
I would never write this for real code for anyone but me, but a backwards iteration trick you can use as a mnemonic is the “goes to” operator -->: for (size_t i = ARRAYSIZE; i --> 0; /* no update statement */) { printf("%d", arr[i]); } (This is actually parsed as i-- > 0, but that way it’s harder to remember how to avoid off-by-one. Also note this version works with unsigned types.)
I've had quite a few cases over the years needing to do this, and eventually I have come to the conclusion that this is actually the "best and safest way" to down-loop as long as we're working with indices. Just accept the pattern/idiom, even though it may look a bit weird at first.
The idiom applies well to copying a (null-terminated) string in C as well: char to[100]; char* from = "Hello, world!"; for (char* c=from, *d=to; *c; c++, d++) *d = *c; It's becomes a one-liner, but since it's easy to forget the null-termination that way, a slightly more obfuscated way might be "better", especially if you are a for-fan: for (char*c=to,*d=from; *c++ = *d++; ); This is another example of "any non-zero value is true" being applied in C coding. (Yes, I know there is _strcpy_ too...)
Better to use an index and not do two increments per loop. If you're implementing strcpy and doing so the naive way: for ( size_t i=0; (d[i]=s[i])!=0; i++ ); is cleaner and easier to understand while being more succinct. But if you're reinventing the wheel, do so with at least 4 byte chunks if not SSE instructions and maybe 16 byte chunks.
@@anon_y_mousse Why is 2 indexed lookups better than 2 increments? The indexed lookups imply 2 additions (ptr+idx) and 1 increment per loop, the latter usually being a superfast trivial operation on most CPUs; compared to only the 2 ptr increments. (Indexed lookups are also more complex and potentially a slower operation.) Reinventing the wheel is the joy of learning how the CPU works or how algorithms work, so it is, or should be, at the heart of programming knowledge IMHO. Anyway, we are probably not so concerned about how "compilers can do a much better job of optimization" in this particular context, but your suggestion to use SSE or multibyte chunks makes an excellent excersize too!
@@benhetland576 Since the processor can do an indexed reference the same as a direct reference, and you'll ideally be using registers anyway, an offset in a register can be cached better and work faster per loop because you're only incrementing once instead of twice.
Well not in explicitely way, you're refering to for eachs loops, that in fact are just while loops that compiles in another abstraction layer of the code generation that your tecnology framework is familiarized with, so to keep it simple, for isn't a good idea in OO languages neither due the irresponsble data mutability that implies their usage
The comma operator is a sequence point, the order is defined from left to right. You might have confused this with the sequencing order of function parameters, which is not defined by the standard.
Man I’ll tell ya coming from node to working on a go project it’s so cramped!!! It drives me crazy they don’t use more line breaks for convention. It’s a sin!
You don't mention if there is a performance difference between a for and while? Is that so compiler dependent that it can't be answered generically or is there a rule of thumb? Cheers.
Hi, Jacob. Could you please give your opinion on the "CuTest" unit testing framework? Should I use that one or criterion if I want to test my C applications? Thank you in advance
It's a funny thing,... as you state here, the for loop is a special case of the while loop. But the while loop came in with structured programming and Algol -> Pascal -> C ... whereas the for loop predates structured programming and can be found in the likes of Fortran IV and BASIC. No particular point to make, just an observation, just a "here's a funny thing".
hi sir . wonderful video on for loops sir can you pls explain how to return 2d array from functions statically because I faced this question in sde interview in abc company ....
bruh your while loop needs to be inside curly braces to be totally equivalent with the for loop. Now you can access i after while loop but not after for loop.
Hey, jacob. Do you have plans for RUclips membership? Love your channel and content, and I'd like to support somehow, but I'm from a poor country and our currency is weak, a cheaper option would be great
I've tried that bit of code, but trying to compile that with GCC v13.1, I get a compilation error stating: ``` example.c: In function ‘main’: example.c:15:35: error: variable-sized object may not be initialized except with an empty initializer 15 | int myvalues[ARRAYSIZE] = {1, 2, 3, 4}; | ^ ``` What compiler are you using there?
With clang the code compiles, just printing out a warning of "variable length array folded to constant array as an extension [-Wgnu-folding-constant]". If you'd replace the "const int ARRAYSIZE = 5;" with an macro like "#define ARRAYSIZE 5" it'd compile with both gcc and clang (and probably any other compiler). Even tho it seems he was using gcc in the video (at 4:50 you can see it after he ran the make command), not sure if anything changed in that compiler regarding this or if it is a configuration thing.
@@benhetland576 yes the for range loop is the only difference but for me it can't get the size of a static 2 dimension array with 2 dimension vector works perfectly
@@JacobSorber Given the way she talks to you, I'm guessing teenager? I'm sorry for your loss. When they reach that age you've lost every battle and the whole war.
@@anon_y_mousse No complaints here. She's no longer a teenager, and in most of our life battles she and I are usually on the same team. It's all good.
@@JacobSorber nice to see her then. I watched your videos from Botswana’s days and your kids featured then too for a brief period of time. I am a native from neighbouring SA so was quite surprised to see you there, virtually that is. You should tell us more about your time there, as it is a mostly a lovely country.
Sometimes I show, just for fun for ( i=0; myProcFunc(i); i++ ); for ( init_func(); eval_func(); ); One I show new embedded programmers, I show: for ( i=0; i
@@michaelkotthaus7120 if you are referring to : for ( init_func(); eval_func(); ); then nope :) But there are rare reasons to do this and it can be confusing, but it shows the understanding of for(), where the items are __RUNCODE__, __EVALCODE__, ___DOCODE__ By doing this, you can exand your eval condition example: int eval_func(int n) { int flg = 1; if (n == 5) { flg = 0; } if (SOMEVAR == SOMECOND) { flg = 0; } return flg; } for(i=0; eval_func(i); i++) { ..code.. } You can compile this src below showing no 3rd item in the for command #include int i; void init_func(void) { i = 0; } int eval_func(void) { printf("iteration: %u ", i); i++; if (i
@@portblock No, I meant the while-loop after "translates to". I miss the increment of i. This is a reason why I also prefer for-loops: with the three common parts (initialization, condition, increment-command), it is harder to miss one.
I observe that you are now approaching Lisp's fundamental Read-Eval-Print loop, which is perhaps claimed to be the hidden underpinnings of every other programming language at their core...
I'm using VS Code with MSYS2 gcc compiler. I'm getting the following error: "Variable-sized object may not be initialized". Some sources on StackOverflow mention that this is due to initialization standardized in C99. It's interesting that memset() function isn't used here. The workaround I've found is using #define ARRAYSIZE 4 instead of const int. I'm wondering if there's something I'm missing in the JSON configurations or missing something in syntax. I'm simply wanting to print each index and value pair of the array with formatted output. Is anyone else having issues with this code from the video? Please advise and provide solution. #include #include #include const int ARRAYSIZE = 4; int main(int argc, char **argv){ int myValues[ARRAYSIZE] = {1,5,8,3}; for (int i = 0; i < ARRAYSIZE; i++) { printf("%d: %d ", i, myValues[i]); } return 0; }
TNice tutorials is actually a very good and straight forward tutorial. No having ask questions or guess, no over-explaining elents, and brings
លោកគ្រូ your daughter is finally back on the video Last time I saw you all in Africa. she definitely looks after you for sure.
It's interesting to see the point of view of a beginner, especially because it's a beginner channel.
nah i think developers from different levels can use this channel as reference
@@justcurious1940 I've not learned much on this channel. I like to watch Jacob teaching, what's his approach, where he stops in the complexity, this sort of things.
As for the value of these videos, I'd say the gain I get is tangential as the more people that learn from you the better the industry gets. On the subject of not needing for loops, C gives us many ways to do things, it is only our desires which push us in a given direction. We could after all use labels, gotos and simple ifs. That might make for a really good video to show how looping constructs break down at a low level. Maybe even demonstrate one of my favorite ways of handling cascading errors.
I would say a for loop enthusiast is one that writes infinite loops this way:
for (;;) {
// code
}
Yes, that is how you spell "forever" in C ;-)
@@benhetland576 I guess having a macro defined as
#define forever for (;;)
is okay, but i find while (1) clearer.
Hi, First of all, great video great content. I have learned a lot from the video series. One thing that I want to add to the explanation is, It's perfectly right to use a while loop for everything but one difference is that my professor told me back when I was in university. If some problem requires a fixed number of iterations or you could say if you know how many times the loop is going to run then use FOR loop and if you don't know the number of iterations like you are reading from a file and the condition is read till '
' then use While loops. I think this makes sense and it makes sometimes the implementation easy.
This video will help coding beginners a lot!
15:34 What I say to myself in half of my code reviews XD
I missed for loops iterating over lists in the video, here is the for loop I always write:
NODE* head = ...;
for(NODE* i = head; i != NULL; i = i->next) { ... }
or simply
for(NODE* i = head; i; i = i->next) { ... }
or if there would have been a '->=' operator in C:
for(NODE* i = head; i; i->=next) { ... }
Aha, found the for loop enthusiast. I nearly always while loop that idiom.
Your merch store is down! I'm taking a c programming for electrical engineers course and wanted that shirt to wear!
Yeah, merchonate went out of business. I'm working on an alternative. Sorry.
I would never write this for real code for anyone but me, but a backwards iteration trick you can use as a mnemonic is the “goes to” operator -->:
for (size_t i = ARRAYSIZE; i --> 0; /* no update statement */) {
printf("%d", arr[i]);
}
(This is actually parsed as i-- > 0, but that way it’s harder to remember how to avoid off-by-one. Also note this version works with unsigned types.)
I've had quite a few cases over the years needing to do this, and eventually I have come to the conclusion that this is actually the "best and safest way" to down-loop as long as we're working with indices. Just accept the pattern/idiom, even though it may look a bit weird at first.
@@benhetland576 I write it as `i-- > 0`, not `i --> 0`, when I’m not using it as a mnemonic.
The idiom applies well to copying a (null-terminated) string in C as well:
char to[100]; char* from = "Hello, world!";
for (char* c=from, *d=to; *c; c++, d++) *d = *c;
It's becomes a one-liner, but since it's easy to forget the null-termination that way, a slightly more obfuscated way might be "better", especially if you are a for-fan:
for (char*c=to,*d=from; *c++ = *d++; );
This is another example of "any non-zero value is true" being applied in C coding. (Yes, I know there is _strcpy_ too...)
Better to use an index and not do two increments per loop. If you're implementing strcpy and doing so the naive way: for ( size_t i=0; (d[i]=s[i])!=0; i++ ); is cleaner and easier to understand while being more succinct. But if you're reinventing the wheel, do so with at least 4 byte chunks if not SSE instructions and maybe 16 byte chunks.
@@anon_y_mousse Why is 2 indexed lookups better than 2 increments? The indexed lookups imply 2 additions (ptr+idx) and 1 increment per loop, the latter usually being a superfast trivial operation on most CPUs; compared to only the 2 ptr increments. (Indexed lookups are also more complex and potentially a slower operation.) Reinventing the wheel is the joy of learning how the CPU works or how algorithms work, so it is, or should be, at the heart of programming knowledge IMHO. Anyway, we are probably not so concerned about how "compilers can do a much better job of optimization" in this particular context, but your suggestion to use SSE or multibyte chunks makes an excellent excersize too!
@@benhetland576 Since the processor can do an indexed reference the same as a direct reference, and you'll ideally be using registers anyway, an offset in a register can be cached better and work faster per loop because you're only incrementing once instead of twice.
Thank you Jacob for this cool video 😎
You're welcome. Glad you enjoyed it.
The lighting .... the audio .... the cringe .... the whole setup .... I'm amazed. Haha. Please keep going, I want to see how this will evolve.
I'm surprised you didn't get into the topic of pre and post increment within the loop counters.
It feels like we should be teaching preincrement rather than postincrement to exactly and directly express intent
Really fun episode!
Yeah in C we don't need for loops but I like the fact that for loops in OO languages takes this mentality and applies it for iterables
Well not in explicitely way, you're refering to for eachs loops, that in fact are just while loops that compiles in another abstraction layer of the code generation that your tecnology framework is familiarized with, so to keep it simple, for isn't a good idea in OO languages neither due the irresponsble data mutability that implies their usage
Isn't the comma operator not defined in which order the statements will be executed?
The comma operator is a sequence point, the order is defined from left to right. You might have confused this with the sequencing order of function parameters, which is not defined by the standard.
This was my question as well especially when compared to something like "x = y++ + y;" which has an undefined outcome.
Man I’ll tell ya coming from node to working on a go project it’s so cramped!!! It drives me crazy they don’t use more line breaks for convention. It’s a sin!
Hey Matthew, your videos are really dope , thank you.
Who is Matthew?
Jacob, what are good projects to work on to practice skills in c?
You don't mention if there is a performance difference between a for and while? Is that so compiler dependent that it can't be answered generically or is there a rule of thumb? Cheers.
Look at them in assembly
Hi, Jacob. Could you please give your opinion on the "CuTest" unit testing framework? Should I use that one or criterion if I want to test my C applications? Thank you in advance
nice
Between Producer and Signature, wNice tutorialch SKU would you recomnd? Is Signature worth the 50% price bump? ItNice tutorialnk I want to have
It's a funny thing,... as you state here, the for loop is a special case of the while loop.
But the while loop came in with structured programming and Algol -> Pascal -> C ... whereas the for loop predates structured programming and can be found in the likes of Fortran IV and BASIC.
No particular point to make, just an observation, just a "here's a funny thing".
Interesting. Thanks.
If not for loops, then for what?
hi sir .
wonderful video on for loops
sir can you pls explain how to return 2d array from functions statically because I faced this question in sde interview in abc company ....
bruh your while loop needs to be inside curly braces to be totally equivalent with the for loop. Now you can access i after while loop but not after for loop.
wow so clever bro i have not thought about it
And: for( list_elem_t * iter = head; iter; iter=iter->next ) { /* Do something */ }
Hey, jacob. Do you have plans for RUclips membership? Love your channel and content, and I'd like to support somehow, but I'm from a poor country and our currency is weak, a cheaper option would be great
I've tried that bit of code, but trying to compile that with GCC v13.1, I get a compilation error stating:
```
example.c: In function ‘main’:
example.c:15:35: error: variable-sized object may not be initialized except with an empty initializer
15 | int myvalues[ARRAYSIZE] = {1, 2, 3, 4};
| ^
```
What compiler are you using there?
With clang the code compiles, just printing out a warning of "variable length array folded to constant array as an extension [-Wgnu-folding-constant]".
If you'd replace the "const int ARRAYSIZE = 5;" with an macro like "#define ARRAYSIZE 5" it'd compile with both gcc and clang (and probably any other compiler).
Even tho it seems he was using gcc in the video (at 4:50 you can see it after he ran the make command), not sure if anything changed in that compiler regarding this or if it is a configuration thing.
for those who don't know the correct C idiom:
for (int i = count; i--;) {
// do stuff with array[i]
}
loops over an array backwards perfectly.
Does clever code compile to smaller\faster machine code?
Not clever code compiles into fast machine code only if compiler developers were clever. So somebody has to be clever
int me = big fan of Eliza's snark and wits
Just to let you know, RUclips has a bug that keeps unsubscribing me from your channel. This has being going on for at least a month.
Who's Eliza?
while(true) {
std::cout
But that is C++ 🧐
@@jackgerberuae i think loop constructs are the same
@@justcurious1940 Not any more. In C++ you can now write things like _for (const auto& element: array) { /*do something*/ }_
@@benhetland576 yes the for range loop is the only difference
but for me it can't get the size of a static 2 dimension array
with 2 dimension vector works perfectly
I'm pretty sure I've seen this video way before.
I gather Eliza is your sister ?
Nope. Daughter.
@@JacobSorber Given the way she talks to you, I'm guessing teenager? I'm sorry for your loss. When they reach that age you've lost every battle and the whole war.
@@anon_y_mousse No complaints here. She's no longer a teenager, and in most of our life battles she and I are usually on the same team. It's all good.
@@JacobSorber Glad to hear it's worked out better for you. For some, teenagers are the death knell of their relationship with their children.
@@JacobSorber nice to see her then. I watched your videos from Botswana’s days and your kids featured then too for a brief period of time.
I am a native from neighbouring SA so was quite surprised to see you there, virtually that is. You should tell us more about your time there, as it is a mostly a lovely country.
Sometimes I show, just for fun
for ( i=0; myProcFunc(i); i++ );
for ( init_func(); eval_func(); );
One I show new embedded programmers, I show:
for ( i=0; i
I think you missed the increment of i in the second version.
@@michaelkotthaus7120 if you are referring to : for ( init_func(); eval_func(); ); then nope :) But there are rare reasons to do this and it can be confusing, but it shows the understanding of for(), where the items are __RUNCODE__, __EVALCODE__, ___DOCODE__
By doing this, you can exand your eval condition
example:
int eval_func(int n) {
int flg = 1;
if (n == 5) { flg = 0; }
if (SOMEVAR == SOMECOND) { flg = 0; }
return flg;
}
for(i=0; eval_func(i); i++) {
..code..
}
You can compile this src below showing no 3rd item in the for command
#include
int i;
void init_func(void) {
i = 0;
}
int eval_func(void) {
printf("iteration: %u
", i);
i++;
if (i
@@portblock No, I meant the while-loop after "translates to". I miss the increment of i.
This is a reason why I also prefer for-loops: with the three common parts (initialization, condition, increment-command), it is harder to miss one.
@@michaelkotthaus7120 ah yes, you are correct! My apologies
I observe that you are now approaching Lisp's fundamental Read-Eval-Print loop, which is perhaps claimed to be the hidden underpinnings of every other programming language at their core...
I'm using VS Code with MSYS2 gcc compiler. I'm getting the following error: "Variable-sized object may not be initialized". Some sources on StackOverflow mention that this is due to initialization standardized in C99. It's interesting that memset() function isn't used here. The workaround I've found is using #define ARRAYSIZE 4 instead of const int.
I'm wondering if there's something I'm missing in the JSON configurations or missing something in syntax. I'm simply wanting to print each index and value pair of the array with formatted output.
Is anyone else having issues with this code from the video? Please advise and provide solution.
#include
#include
#include
const int ARRAYSIZE = 4;
int main(int argc, char **argv){
int myValues[ARRAYSIZE] = {1,5,8,3};
for (int i = 0; i < ARRAYSIZE; i++) {
printf("%d: %d
", i, myValues[i]);
}
return 0;
}