Тёмный

How to Implement a Stack in C (+ encapsulation) 

Jacob Sorber
Подписаться 165 тыс.
Просмотров 60 тыс.
50% 1

Опубликовано:

 

26 сен 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 108   
@zachzulanas4125
@zachzulanas4125 4 года назад
you are honestly the reason why I actually like C and understand it, your videos are so clear and concise, I wish I could have you as an actual professor!
@JacobSorber
@JacobSorber 4 года назад
Thanks, Zach. Glad I could help. I'll be teaching OS this fall at Clemson, if you want to enroll. 🙂
@zachzulanas4125
@zachzulanas4125 4 года назад
@@JacobSorber wish I could :( I'm at UCSC, and I'm in my Systems class rn, your videos have been a godsend, especially the threading series, our professor had us build a server with sockets but barely went over them in class, more just the concepts.
@axalius572
@axalius572 4 года назад
You're the only person on youtube, I'd take an online course from.
@KorayUlusan
@KorayUlusan 3 года назад
corey schafer's python playlist is awesome too!
@brijeshsamal7035
@brijeshsamal7035 3 года назад
Jacob - go-to for learning C related stuff. Kevin Powell-CSS, Tech With Tim/ Corey Schaefer-Python. Most others are pretty random.
@Mishiman
@Mishiman 4 года назад
4:00 you could pass a pointer to an int to pop() so you can check for errors, like so int pop(int *error) { if (stack_empty) *error = 1; return 0; *error = 0; return value; } and then int error = 0; int value = pop(&error); if (error) { ... } else { // do something with the value... } It's a bit more verbose but I think that's the best solution
@yourf4104
@yourf4104 9 месяцев назад
just use errno :D
@johnnewton2340
@johnnewton2340 4 года назад
Great job! Could you make a video about "Difference between system call and function call" ?
@JacobSorber
@JacobSorber 4 года назад
Absolutely. I just added it to my topic list.
@soumyadipsaha8904
@soumyadipsaha8904 4 года назад
yes please
@marcossidoruk8033
@marcossidoruk8033 3 года назад
Function call is when you call a function using the standard calling conventions (arguments should be pushed to the stack in reverse order, then the return adress, etc etc), a system call is when a program runs kernel code, there are two ways in wich this may happen: The progran triggers an interrupt, that is a specific CPU instruction that interrupts the execution of the program and passes control to the os or the firmware, the OS generally takes the arguments for the interrupt from the cpu registers. Interrupts are very slow thoug, so modern operating systems often load the part of the kernel code needed for syscalls into the memory allocated for the process, thus allowing the process to make systemcalls as if they were just another function without messing things up.
@samuelrasquinha6712
@samuelrasquinha6712 4 года назад
You really have a passion for code and teaching. Thanks a lot for these high quality, amazing and to the point videos. Good Luck.
@JacobSorber
@JacobSorber 4 года назад
Thanks!
@dbgn
@dbgn 4 года назад
Hi Jacob ,I found your channel recently and you are amazing teacher. Can you make more in depth tutorials about operating systems ,networks ,compilers for those of us ,who can't affort college. I really think you are amazing teacher ,your students are lucky.
@anjalibhatt56
@anjalibhatt56 4 года назад
Thank you for designing this course. Eagerly Waiting for it😇
@jakubstandarski7974
@jakubstandarski7974 4 года назад
Amazing job! Everything clarified in a very simple way and accordance with words of Albert Einstein: Everything should be made as simple as possible, but not simpler.
@sumitbhosale3401
@sumitbhosale3401 4 года назад
Very Nice Explaination Sir. Thank You. Can You make video on graph in c. cause it is so hard to learn
@JacobSorber
@JacobSorber 4 года назад
I'll add it to the list, and see what I can do.
@R4ngeR4pidz
@R4ngeR4pidz 4 года назад
for int pop() you could give it a pointer, if you can pop something you assign the value to that pointer, and return true otherwise you return false
@JacobSorber
@JacobSorber 4 года назад
Hi Thijs. Good to see you again. Yes, you definitely can. I tried to keep things simple, so I don't confuse people who still are settling in with pointers. But, you're absolutely right.
@dedswift
@dedswift 4 года назад
Amazing video. Can you please do one about graphs ?
@JacobSorber
@JacobSorber 4 года назад
Definitely. It's on the list of future video topics.
@gautamkumarshukla3055
@gautamkumarshukla3055 3 года назад
At line number 14 , top++, we have incremented the index . Then setting the value at that index. Because of this we may miss the index 0 to set value at . I believe it should be " mystack[top++] = value;"
@sverkeren
@sverkeren 2 года назад
No, empty stack has top=-1, so first push will land at index 0.
@iversonvarun
@iversonvarun 4 года назад
Love the content. I would rather be interested in a more advanced embedded systems/operating systems/C programming course.
@timwmillard
@timwmillard 4 года назад
Thanks Jacob. Another great video.
@JacobSorber
@JacobSorber 4 года назад
Thanks, Tim.
@eugenek.9959
@eugenek.9959 3 года назад
I have rewatched this part a thousand times and still struggling to understand... newnode -> next = head; head = newnode; what is that done for?
@JacobSorber
@JacobSorber 3 года назад
Drawing it out might help. Basically, you're adding the newnode to the front of the list. You do that by pointing the newnode's next pointer to the current head. And, then you move the head pointer to point to the new node. So, in the end, you have your head pointer pointing at the new node, and the chain remains intact.
@eugenek.9959
@eugenek.9959 3 года назад
@@JacobSorber Thank you very much for the reply. My main problem was that I imagined *next pointer of each node to point to new node that's being pushed, and not vice versa. I guess I've seen a lot of visualisations of stacks without actually saying that
@frezajoe5836
@frezajoe5836 2 года назад
is it possible to implement a stack with different type of data in it? like how routine call stacks works under the hood
@Thanos-hp1mw
@Thanos-hp1mw 5 месяцев назад
We will need void pointers and unions for that I'm sure...
@TinBryn
@TinBryn 3 года назад
C actually has a really good encapsulation story, you can put in a header. struct stack; struct stack* new_stack(); void push_stack(struct stack *mystack, int value); int pop_stack(struct stack *mystack); void delete_stack(struct stack* mystack); and that's it, with this you can write and compile (but not link) code using only this, not only do you not know the implementation, it doesn't even have to have been written at this point.
@DreamVikings
@DreamVikings 2 года назад
Hello. Im a scrub desperately researching stuff because i have an interview soon. I believe that by "encapsulation" you actually mean "abstraction". Encapsulation, as I understand it (This is from an OOP video I watched) relates to access levels, but presenting the information in a way that hides the back of the code from the user / programmer working on code, is abstraction. Again, im kind of new. Could be wrong.
@jayflaherty5260
@jayflaherty5260 4 года назад
Have you thought about exploring Rust as a programming language to help students write safe, performant, and concurrent systems level code?
@JacobSorber
@JacobSorber 4 года назад
I have. I like Rust. As it becomes more mature and available on different platforms, it's definitely a solid option.
@jayflaherty5260
@jayflaherty5260 4 года назад
@@JacobSorber it hit v1.0 5 yrs ago (1.45 now), async/await is now in the core, and Microsoft has WinRT, and its available on all platforms LLVM is available. Looking forward to more Rust videos!
@makanbanyak3957
@makanbanyak3957 4 года назад
thanks for making videos.
@GCAGATGAGTTAGCAAGA
@GCAGATGAGTTAGCAAGA 4 месяца назад
Hi! Nice tutorials. But I can't understand something: in 10:23 you passed *mystack pointer into a pop function. Than inside this function you used star operator with an arrow operator - after dereferencing a pointer basically. Why is it so? I mean *mystack isn't even a double pointer.
@ask4144
@ask4144 4 года назад
I watched your video about the linked list I feel like a stack is just a kind of linked list
@JacobSorber
@JacobSorber 4 года назад
A stack is an abstraction, that can be implemented using a linked list or an array, or as a block of memory and architecture and register-assisted pointer arithmetic (as is the case for your program's call stack). But, yes, when you implement it with a linked list, it feels like a linked list with some restrictions applied to it.
@ask4144
@ask4144 4 года назад
@@JacobSorber thank you! I'm working on a project (sat solver) and this video is very helpful.
@rustycherkas8229
@rustycherkas8229 2 года назад
@12:30 - If the array's stack index started at zero (index of first store location), and it was incremented after a successful copy ( ie: stack[ idx++ ] = value; ) there would be no "funny business" initialising to -1... Pre-decrement, if possible, when popping the top value off the stack: ( value = stack[ --idx ]; ) idx is the (unsigned) count of the number of items currently on the stack. Bounds checking has been left as an exercise.
@bonbonpony
@bonbonpony 4 года назад
01:25 That's why I often use a metaphor of a one-ended pipe/tube ;> Because this disallows cheating. The only way to get something out of the bottom of a one-ended pipe is to first remove all the objects that are lying upon it, one by one. 01:40 Well, there's also `peek`, which allows you to look at the element on the top of the stack without the need of removing it. Sure, it could be implemented with `pop` followed by a `push` of the same thing, but `peek`ing is faster and doesn't really break the invariants ;) Same thing with a variant of `peek` that can peek an `n`th element counting from the top of the stack, because it can be simulated with `n` calls to `pop` followed by `n` calls to `push` to restore the original layout of the stack. Another useful thing might be `dup` which duplicates whatever is currently on the top of the stack. This one is equivalent to popping it once, then pushing it twice. But yeah, in terms of interfaces, those could be implemented as external helper functions on top of `push` and `pop`, while `push` and `pop` are crucial. But I think there might be a couple of "methods" that are as crucial as `push` and `pop`, and can be considered a part of the stack's interface: checking whether it's full/overflown (unless it automatically grows), and checking whether the stack is empty (this one is quite crucial).
@makveli259
@makveli259 4 года назад
Algorithms in C?
@xwaazes6375
@xwaazes6375 3 года назад
I suppose you could create a constructor method like stack* newStack(){ stack* this = malloc(sizeof(stack); this->top = STACK_EMPTY; return this;}. A little too C++-esque but I believe that makes the job.
@atkuriajaykumar3701
@atkuriajaykumar3701 4 года назад
Thankyou sir I watched upto implementation with array since I don't know what is linked list .I will watch it and then come back.basically I don't know nothing about programming can you please suggest me what to do
@fabianmelo9672
@fabianmelo9672 2 года назад
Impressive how Matthew McConaughey knows about C
@sukivirus
@sukivirus 3 года назад
Hey Jason, great video! I am trying to follow your video creating stacks but I wish to create a stack for any data type. How can I do it please?
@sheikhsakibulhasib6208
@sheikhsakibulhasib6208 3 года назад
Vai ... Shei SHei!!! AWESOME!!
@zukunftentwickler3824
@zukunftentwickler3824 4 года назад
Hi Jacob, thanks a lot for your great videos. I really like the setup you are using in visual studio code for your examples, can you just give more information about? Thanks in advance.
@JacobSorber
@JacobSorber 4 года назад
Thanks, Herr Entwickler. So, just to clarify, you are looking for more information about my setup? It's pretty standard. Are there specific things you are wondering about?
@MrCiberedgar
@MrCiberedgar 4 года назад
Hi Jacob!, I tried to implement the stacks with linked lists as you showed in the video, and everything worked like a charm, till I added a function that creates a dynamic array with malloc, now if I give that array a size bigger than the amount of elements in the stack it won't pop any element for some reason. Any tips on how to solve this? Amazing videos btw!
@Stomachbuzz
@Stomachbuzz 3 года назад
I don't quite understand you would create a stack manually? Isn't the stack something that the compiler creates to fit your code? I understand to explain the logic of the stack, but why am I doing the job of the compiler?
@JacobSorber
@JacobSorber 3 года назад
Well, there is "THE STACK" meaning the call stack, and then there are stack data structures. The call stack is one stack and it is managed by the compiler. But, developers often use other stack data structures to manage various issues in their applications.
@alacastersoi8265
@alacastersoi8265 3 года назад
Can you do a video on alignment in c and _Alignas?
@peacemekka
@peacemekka 3 года назад
I'm still scratching my head. Tutorial was good but I didn't really understand. I might have to practice.
@JacobSorber
@JacobSorber 3 года назад
Practice is good, but feel free to ask about anything that's confusing.
@peacemekka
@peacemekka 3 года назад
​@@JacobSorber Okay so I tried the linked list one and I had trouble getting it. Then I went and wrote myself explanations for each line. And I think I get it somewhat now. Its not easy but atleast it makes sense. Will take me a few more goes before I understand properly. I suck at Data Structures. I slept through most ds classes throughout my semester. Regret it now.
@ThasinAkhand
@ThasinAkhand Месяц назад
can you use malloc and then realloc?
@SimonJentzschX7
@SimonJentzschX7 4 года назад
I love watching your videos. One Question about encapsulation: In order to keep the implementation flexible we don't want to make the details public. So many projects are using void* as types. In your example the functions pop() and push() could also use a void* (or a typedef to void*) instead. What do you think of this approach?
@JacobSorber
@JacobSorber 4 года назад
Good question. I think it really depends on what you're trying to protect against. With void* you lose any type-checking help that the compiler could otherwise offer. And, it doesn't prevent people from messing with it, but rather just makes things opaque, which probably does discourage most people from messing with the internals. Whenever possible, I like to keep the compiler's type checking as an ally in my quest for robust code.
@SimonJentzschX7
@SimonJentzschX7 4 года назад
@@JacobSorber I agree, so far we talked about it in the team but we did not want to lose the help of the compiler. One option though would be to havean public and an internal header file. And for the public header-file we could replace the struct-def with void, because when linking to a library you don't need the internal struct anymore.
@TheCocoaDaddy
@TheCocoaDaddy 4 года назад
@@JacobSorber Yep, the compiler is your friend. :)
@EnjoyingBacon7
@EnjoyingBacon7 2 года назад
What’s the point (at 8:46) of the temp node?he creates it, doesn’t use it, then frees it… I don’t get what it’s there for…
@rustycherkas8229
@rustycherkas8229 2 года назад
tmp points to the 'head' node that is going to be free'd (temporarily hanging onto its address). The head pointer is changed (and aren't we glad we kept the old value?!) Now that the head pointer has been 'advanced', the node that WAS at the head is free'd.
@bauglirmelkor5778
@bauglirmelkor5778 2 года назад
doesn't "stack *mystack" is the same with" node **mystack" since stack type defined as "typedef node * stack;" why do we need pointer to pointer?
@newb_embedded040
@newb_embedded040 5 месяцев назад
To pass by reference in push and pop. Oherwise it won't update inside those function.
@aabdev
@aabdev 4 года назад
Dear Jacob Sorber , What determines in which direction the RAM function-stack will grow? In my MCU (SPC58) stack grows from big RAM address to low RAM address. Is that HW determined? Is it possible to reverse function-call stack direction in compiler options? Warm regards, AB
@JacobSorber
@JacobSorber 4 года назад
Since push and pop are usually operations defined by the architecture, this question is very hardware dependent. Some processors grow the stack upward (8051, I think), and some are selectable (ARM, I believe).
@marusdod3685
@marusdod3685 4 года назад
you could use encapsulation by hiding some of the implementation in a c file
@mohdzeeshan5287
@mohdzeeshan5287 3 года назад
Hey .. can you make a video on 'tries' please?
@JacobSorber
@JacobSorber 3 года назад
Yes, it's on my rather long list of future video topics. I'm not sure how long it will take me to get to it.
@brudra0
@brudra0 5 месяцев назад
Which editor is this ?
@ajilraju355
@ajilraju355 4 года назад
Nice video
@JacobSorber
@JacobSorber 4 года назад
Thanks, Ajil.
@LinucNerd
@LinucNerd 4 года назад
If you have a function that should return a value, but should also return a value if something went wrong, the best way I've found of distinguishing the return value from an error, is to just use pointers. If all is well, return a pointer to the value, else if something went wrong, return NULL. That may not always work, and so sometimes I've had to get a little tricky, and instead make the function itself write to an address if something went wrong, like so: int test(int *error) { // Sorry, tabs in comment section no work :( if (/* something went wrong */) { *error = 1; return 0; } return value; // Some normal value } After I watched this video, I was reminded or errno... Would it be wrong to use errno for these sorts of things? Or, what is the best way of dealing with this?
@JacobSorber
@JacobSorber 4 года назад
If you were going to return a pointer, I would just malloc space for the result, and return the pointer. That way NULL, could be your error state, and anything else is a valid result. If you don't mind the extra time for a malloc call and the responsibility of eventually freeing it, then this is a really good way to go. I personally am not crazy about the errno approach. Global variables come with a lot of baggage-probably not going to work well with threads. I would specifically avoid errno, since it's used by a lot of other functions, and you could run into issues. You can also pass in a pointer to where you want to popped entry to go and return the success/failure as the return. Lots of options.
@RockTo11
@RockTo11 4 года назад
Malloc would be slow. My advice would be to use an output parameter. Maybe something like: int stack_pop(int* success); int success; int result = stack_pop(&success); if (success == 0) printf("stack empty "); else printf("result: %d ", result);
@leocarvalho8051
@leocarvalho8051 4 года назад
i did not get (*stack)->value . Why are you deferencing a pointer but then using the arrow thing???
@thebigmacd
@thebigmacd 4 года назад
He's pointing to an item within the struct to which the pointer pointed.
@Thanos-hp1mw
@Thanos-hp1mw 5 месяцев назад
Because stack is a pointer to a pointer. Meaning *stack is also a pointer.
@socat9311
@socat9311 4 года назад
I did not get why pop cant return bool similar to push?
@JacobSorber
@JacobSorber 4 года назад
pop is returning the thing that was removed from the stack. So, if pop returns bool, then you would need some other way to get the popped value back, maybe through a pointer passed in as an argument. You could do it that way, I was just trying to keep things simple.
@socat9311
@socat9311 4 года назад
@@JacobSorber ah makes sense i thought it was more a "confirmation" function that says if the element was removed. Thanks!
@mlfconv
@mlfconv 3 года назад
What kind f editor do you use I though it was atom at first sight
@michalski9141
@michalski9141 2 года назад
late reply but its vs code
@no_name4796
@no_name4796 2 года назад
How to create a stack in c: use recursion in a smart way ;-)
@p99chan99
@p99chan99 9 месяцев назад
Can you explain? kinda a newb at data structures but I never knew you could implement a stack using recursion
@soniablanche5672
@soniablanche5672 8 месяцев назад
how to implement a stack in javascript: const stack = [];
@magno5157
@magno5157 4 года назад
I know you just want to show what a stack is. However, could you please not make examples using global variables? It encourages people who don't fully know all about global variables to use them. It's bad if they don't know there can be only one definition for each global variable anywhere in the program *unless* it has internal linkage (and even so there can be only one definition per translation unit). See, global variables are not that simple to people who don't understand linkages.
@tsunningwah3471
@tsunningwah3471 7 месяцев назад
bbbbbbbbbbbbbb
@soumyadipsaha8904
@soumyadipsaha8904 4 года назад
please make a video on block devices and interrupt handling
@kc2838
@kc2838 4 года назад
Eagerly waiting for your course. Plz Use C/C++ for the codes in the course also.
@JacobSorber
@JacobSorber 4 года назад
But, of course.
@cuongnguyenhuu1279
@cuongnguyenhuu1279 4 года назад
Pls make video about implement tree and graph in C.
@JacobSorber
@JacobSorber 4 года назад
It's on the list. If all goes well, you'll see it in the coming weeks.
@milnueve89
@milnueve89 3 года назад
Thanks for your instructive video! I'm self-taught, and I'm reading the book "The C Programming Language" by R&K. In this book on page 66, they implement a stack with an array for a Reverse Polish Calculator initialising the value of "top" at 0 instead of -1, actually "top" is named "sp" instead (stack position). So in push() you first push the value and then you increment "top", and in pop() you return the value with the index "top" decremented. The question is, wich alternative is most commonly used? In addition: Is one better than the other? I appreciate your time. Greetings!
@philperry6564
@philperry6564 3 года назад
The implementation in the book is very good. Personally, I'd only use negative values, implicitly, for error handling but each his own. His pointer based implementation is probably the preferred/more efficient and flexible method.
@rustycherkas8229
@rustycherkas8229 2 года назад
If you start the stack 'index' at 0, it conceptually hangs together with all that you know about arrays in C. The stack index tells you how many items are on the stack (like strlen() tells you how many chars are in an array) and where the next item pushed will go: int stack[ stackMax ], idx = 0; bool push( int val ) { if( idx == stackMax ) return false; stack[ idx++ ] = val; return true; } bool pop( int *val ) { if( idx == 0 ) return false; *val = stack[ --idx ]; return true; } Ideally, idx would be an unsigned integer type because it is a 'counting number'. You can have 2, 1 or 0 chickens, but you can't have -1 chicken...
@sumitbhosale3401
@sumitbhosale3401 4 года назад
Also What is search.h in c programming.
@JacobSorber
@JacobSorber 4 года назад
Header file for built-in hash table functionality. (XPG4.2 standard)
@yagami-light
@yagami-light 4 года назад
how do I make it work for any data type and not just int? please help me with this make a tutorial on using void pointers It would be really awesome please help
@JacobSorber
@JacobSorber 4 года назад
A void pointer is just an integer, that happens to be interpreted by the compiler as a memory address. So, moving from int to void * should change almost nothing in the code.
@yagami-light
@yagami-light 4 года назад
Thank You for Answering
Далее
How to Implement a Queue in C
7:53
Просмотров 62 тыс.
How to Implement a Tree in C
14:39
Просмотров 95 тыс.
Help Me Celebrate! 😍🙏
00:35
Просмотров 13 млн
The Call Stack and Stack Overflows (example in C)
12:56
Should you avoid linked lists? (linked list vs arrays)
17:04
How to make memory read-only in your C programs.
12:57
Naming Things in Code
7:25
Просмотров 2,1 млн
are "smart pointers" actually smart?
9:44
Просмотров 75 тыс.
How do I access a single bit?
11:07
Просмотров 21 тыс.
My 10 “Clean” Code Principles (Start These Now)
15:12