Working with pointers is easy af... Just try different permutation and combinations of & and * until code works like u wanted it to work... Don't complicate easy things.. xD 😁😁
One important clarification. The asterisk(*) is an attribute of the variable not the type which your explanation seems to suggest. This distinction is important because if you consider the following line: int* x, y; x is a pointer to an int while y is just an int. If you wanted both to be pointers you would need to write something like: int *x, *y;
@@FriedMonkey362 It's up to you. That is how I prefer it as I feel it more accurately reflects the syntax, but Strourstrup (founder of C++) actually prefers it *int* pX;*. There is not "right" way per say, so do what you think makes sense : )
but int * x, y; is just a syntactic sugar to condense on one line this: int * x; int y; during declaration phase the * operator is treated like the type of memory you'll allocate, otherwise it becomes a unary operator to dereference pointers. so when you declare variables it actually makes sense to read "int * x" as "x is a pointer to int" and otherwise, seeing "*x = y" as "assign y to the address pointed by x"
C++ was the first language I learned.. and I only spent a short time with it. But one thing that made all the difference was having a mental model of computer's memory with addresses and values. Before I knew to do that, C++ was incredibly frustrating. This video is smart to lead with that lesson.
Same, I taught myself C++ well over a decade ago at the wee age of 12 and it took me near 2 years to get pointers. I remember what finally made it click was an analogy comparing it to actual mail addresses, will never forget that enlightening moment.
@@imt3206 in my case, learning how computers handle memory is automatic with learning pointers and data structures like array, stack, qeue, linked list. especially linked list, that shit opened my eyes how linked list is so much superior than array in most cases
I'm a senior majoring in Computer Science at college. If you're a young person whose looking to learn about programming and computers, keep watching this guy's stuff! All complex systems can be broken down to simpler parts. That's what this channel does very well when explaining complex concepts like pointers. This is the first video I've seen but I'm definitely subbing cuz this guy not only knows his stuff but more than I do! My college experience was incredibly lacking in low level courses, which I imagine will be the case at many other universities in the coming future. High-level problem solving has it's place, but low-level is important because a house won't last without a proper foundation. The foundations of computer science are the most important area to master, arguably more important than programming itself. Don't be a cog; be the future.
What programming languages were pushed at your college? My college is pushing C++ right out of the gate and forces us to learn Assembly as well. Is your college similar?
Understanding references, pointers, smart pointers and memory is gamechanger and is crucial thing to know. Dont give up trying to understand, it is well worth it and with bit of practice becomes normal to read and understand. I regret giving up programming because of this at school, it would have boosted my career as software engineer forward by years had i put more time into it.
But can’t find practice problems online. So far being working with this company for about 7 months and everywhere in the codebase we use pointers and I just get more confused especially when a pointer or reference is passed to a method and returned from a method
@@abdiasisibrahim5903 best practice i got was when i tried to make my own simple tile based farming game, so i suggest trying to create something of your own, and when problems arise you need to understand and solve them. I didnt ever finish it, so i cant really show how code looks like, but one of many problems i had was how to grow plants, which I resolved by creating timer, to which I subscribed selected plants and called grow method on them when timer said it is time. Problem also included how to unsubscibe them correctly. Another issue arised when my game grew too much and I had to split it in smaller modules, so eventually I needed to separate drawing routines from game logic. I remember it being tricky, as my game directly extended from engine. I stored tiles and other assets in raw arrays stored at heap, so it also needed some thought to put into. Such practice directly tests your knowledge and teaches you a bit about design patterns and how memory and language works.
@@abdiasisibrahim5903 you use a memory searching tool such as cheat engine to find interesting in game stuff such as player health, some debuggers also have this functionality. Then use relevant os APIs to retrieve a handle to the process and modify data at the found addresses
I struggled quit a bit with pointers and references back when I was learning C (my first programming language,) but I did not gave up and eventually managed to understand them. They're so simple, yet so powerful, and open up an almost infinite number of possibilities. Sometimes, I managed to break programs when using pointers, but in general I have no problem using them 😄
can you help me with this, i on to writing a leetcode problem of merging two sorted list, and cant understand understand this line, struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) { } will you please explain, i had wasted probably 2 hours and still cant understand..
The best tutorial so far. This is what high lever languages do all the time with "references" which is just a pointer bound to a value but you cant play with the pointer directly only the value he is pointing too.
I don’t fully understand everything, but you make me feel like I will one day…and that’s the most important thing I enjoy the most! It’s all about the journey of learning and not always to the final destination! Thank you for this content!
i actually appreciated pointers more when i started to learn golang! it really helps especially when you don't always want to expect a return type when making a function and just modify a value that you pass into
Yes, that's called passing by reference, and it's a very useful feature in many languages to save function call overhead and to return multiple results from a function.
One decent example can be seen in Visual Basic (just the first one that came to mind), where a methods are assigned a role: either a subroutine (no return value) or a function (has a return value). The function/subroutine parameters can also be prefixed with “ByVal” or “ByRef” depending on what you are going to do with those arguments. It’s quite flexible, but sometimes a bit difficult for some to understand
Video idea: How malloc() works and how does it know what memory is considered "free to use". I started programming on retro game consoles where you know ahead of time exactly how much RAM you have at your disposal, so allocation functions in general are very "alien" to me.
I figured as much since MS-DOS had a "malloc" feature where you would tell it how much menory you needed and DOS would tell you where it is. But how does the OS know then?
@@williamdrum9899 it's still the same on any OS if I'm not mitaken. The OS has a map of available memory blocks allocated to your program (called pages). When you call malloc, which is a system call, the OS finds a contiguous space of memory allocated to your program where the size you asked for would fit. If not enough memory is available in your page, a new page is allocated to your program.
About to finish my computer science degree, and I never really understood pointers because most modern languages abstract this. It's nice to make a full circle though. Thanks!
Understanding isnt hard, applying it cleanly is. Working by bypassing scope might be faster but the need of keeping track of it is hard lest one gets memory leak. Not to mention in bigger teams having to rely on coworkers to apply it cleanly. It becomes a cascading problem with less avenues to debug such bugs. edit: 1yr on seems my post got some traction, I want to add something. One of many uses and evolution of a Computer is to be a better Calculator. To that end, computers must be able to provide to a user mildly complex logical constructs/objects on which mathematics can be applied and work on them e.g. plus symbol signifying Concatenation of String objects. One should be able to develop some function without having to think of this and that memory allocation. Usage of pointers should only be approached by the top 1 percentile of experienced devs who is probably designing a solution for other devs; or embedded devs having to work with low level resources but won't have a cascading problem.
Exactly, all these videos explain the concept well, but the real problem is when you are coding something and you dont really understand why you need to use a pointer
Thanks! This is the most explanatory and easy to understand video about pointers so far! I've been writing code for ages and never really wondered about how pointers work. Just started with C and your video really helped.
The int * can be looked at as the type - it's a pointer to an address space sized to fit an int; bear in mind that different machines or different compilers/options can have different size ints, and declaring that size will let the compiler generate binaries allocating the right number of bits of memory.
this comment touches on something i REALLY hate about C. as far as I'm concerned, char is a fundamentally different type to an char*. which, it is. they're a different size and everything. so WHY can we write declarations like "char a, *b;" creating two variables of fundamentally different types in the same statement? it's stupid and i hate it.
@@SoulSukkur back in the old days people couldn't type very well. And monitors were very low resolution, limiting the number of characters and lines visible. So characters had to be conserved.
I first learned about pointers while trying to make Whack-A-Mole with an Arduino. I wanted to pass a “mole” struct into a void function to mutate it, but couldn’t figure out why it wasn’t working… wish I’d seen this video back then; it would’ve saved me several hours of confused googling lol
5:13 You can also say that if there was no asterisk, you would put the value of the pointer pX, which is a memory address, to the variable Y. You want the value of that memory address, so you put the asterisk there.
I’ve never really used C so i’m more familiar with the newer languages masking this functionality. Listening to this video is really easy to absorb. Honestly if you can show more examples of pointers in a part 2 i think someone could really solidify the knowledge quickly!
@@LowLevelTV hi I am seeing your videos from a week I noticed that your explanation made all our ways clear in doubts but I have a question in this pointers topic on embedded c ? The question was why pointers don't use in embedded c Can you pls clarify the following questions with your explanation I had this doubt after watching this pointers topic in your channel...
@@ramakrishna4092 Rama, here's an answer to the common question "why we have to use pointers in embedded C". If you use the Pico/RP2040 SDK, you have to use pointers, the functions in the SDK demand that, and I think it'd be almost impossible to code for RP2040 in C/c++ without the SDK. As LLL says at 6:44, I figure the RPi programmers used pointers to get around scoping issues. They had to do it this way, so we do as well.
I found pointers inheretly easy to understand when i was learning them, what can be hard, for me at least, is how to implement them in an effective way. I can understand the difficulty, since it involves computer memory.
Great explanation, i think the reason why pointers are so widely misunderstood or hardly understood is the lack of explanation regarding memory layout (which you explained really well) and the not so intuitive syntax
@@LowLevelTV umh, not to shoot you down or anything, but if i were being honest, this was like basic stuff. it's fine. the real problem i face is with 2D arrays, and passing them to functions. the one you explained was just plain variables - it was not at all hard for me. even 1d array is managable, but i can never get pointers to work with 2d arrays, and i thought u'd cover those too....
I didn't know what a pointer is but this video is so clear it makes perfect sense. I've watched hundreds of videos over the months and yours are some of THE best. Well done, and much appreciated.
i have found that sometimes when i am really, *really* struggling to understand a concept it might simply be a product of obsessively trying to understand it, so your looking at like 50 interpretations of what a function is and bombarding your brain with too much information for the actual concept to have any cohesion. i remember reading that the best way to remember something is, well, i am going to inject the first part 1. apply what you learn to something you care about 2. repeat it [use it] 10 times in a row
The thing that was the most confusing for me was the syntax and all of it clicked when you simply explained that the star is used for two different things. I just couldn't understand why star next to type is a pointer but star next to variable is a value under the pointer
" star next to type is a pointer but star next to variable is a value under the pointer".. Exactly! I think most tutorials seem to fixate on the memory map element of pointers, which imo isn't that hard to understand. It's the subtly contradictory notation that's that actual source of confusion for most.
Great video, but I think it required more examples of the applications of pointers. Beginners tend to have a small scope of the concept of pointers with a simple explanation. But honestly to me, pointers can never be explained. Its concept and applications can only be truly understood once we've experimented with it hahaha.
Basically if you want to pass a huge struct to a function , instead of copying the whole thing in (ie via the copy by value parameter), pass it in by pointer/reference. Of course if you modify the struct in the function it modifies the original.
using a double pointer to create two dimensional structures(rows, cols) has been one of my favorite things to learn in college so far, and it goes deeper when you figure out you can create other pointers to increase the size it gets crazy
I really understood pointers when I got into embedded programming, where you have to access builtin memory address (registers), read their state or write to them. But wait until you get into typecasting pointers, that gets really fun.
And also doing dangerous thing like this is allowed in embedded C bare metal. pointing to random memory. uint32_t *random_mem = (uint32_t*)0x200800FF; *random_mem = 0xEF; //cause weird behaviour or hardfault.
If you have an array of structs, a pointer would be like passing the number inside the brackets, like array[0] or array[3] etc. As C pre complies everything in to tetris blocks repeated at a fixed interval, as each struck inside the array are 12bytes in size (example), so now you can refer to struct members with and offset of 0 to 11, you just pass base number to the functions, an absolute address in memory that is the base number to each "apartment block" and that is called a pointer.
0:12 I only just started learning C++, but I figure pointers are probably the best part of the whole language, and I'm super annoyed that I wasn't able to read an integer as a string using them, I asked someone who knows more about it than me and they said that Windows doesn't want people doing that kind of thing, something like "That could break your computer irreparably if it was allowed," or that I would need Windows Pro instead of Home to do it, what does Windows know about what I want to do with my device? Bogus! If only Windows didn't have corn cob up their but and would let us directly alter the byte tape, it would be most ideal if there was a BrainF interpreter/compiler that used the actual byte tape instead of just a simulated byte tape that is stored on the actual byte tape to keep things safe.
I dont quite understand why you are talking about byte tape and stuff... but you totally should be able to cast a integer pointer to a string pointer, if thats what you mean. Not that its a good idea lol
@@BetaChri5 Sort of what I want to do, but I don't want it to just make an integer 32 become a string "32," that's boring. I want it to rip the binary representation of the integer out and into a string instead. Without any conversions behind the scenes. Not even adding a null pointer to make sure that the string has an end to it.
Thank you for the explanation! Pointers took me about two years to be able to use them, but I legit just never understood why, other than that we could manually delete them as needed. Never understood why my code would work or not work with or without pointers, but understanding the static and dynamic part really helps
I come from the field of PLC programming. Until recently you could only program most PLCs with either a graphical programming language (good for logic tasks) or in assembler of the PLCs processor. (Good for data tasks). Pointers were really to only way to implement a loop with a pointer iterating over a given field of data. The good thing is pointers and memory handling are really easy in PLCs compared to PCs, so learning pointers there was a good start.
I learned to program PLCs in tech school about 3 years ago. I tell you this RN, my instructor would've thrown me out on my ear if he ever saw a pointer in my code. He nearly did so when I found the JMP command all on my own, especially after I (mis)used it and created an infinite loop. Apparently, not even he used the JMP instruction regularly in some 15 years of PLC coding, so he was in no position or mood to look at my code, see that there was a JMP going up the ladder instead of down, and correct it before problems arose.
Pointers in x86 asm aren't terrible. Basically it's just passing an address for some data as an argument. Where it would trip me however is just the way it looks in C. That is going to take some getting used to.
Before I did week 5 of CS50 I had the impression that complex data structures just need arrays/lists and that’s it. But now I realise how bloody amazing these things really are. The fact you can link multiple things together all using pointers was such an eye opener when it comes to programming.
I learned pointers by starting out with JS, then learning about how computers work on the low level, then learning cpp, and trying out pointers. By then it was relatively intuitive lol
Thank you. My professor is making a huge deal out of pointers and how difficult they will be, but with this video, they seem to be fairly simple and useful. Thanks.
I think what caused the most confusion for me regarding pointers was when using * as the indicator that a variable was a pointer and using the same symbol to de-reference.... I think it would have caused much less confusion if we didn't use the asterisk for both
@@dadoo6912 it's to do with the whole idea of "declaration follows use". The asterisk is on the variable name because in some weird way, it acts as the dereferencing operator within the declaration. Something like `int *pX` really means (in terms of the declaration semantics) "`pX` is something that can be dereferenced (i.e. a pointer) and when you dereference it, you get an `int`." Similarly, `double a[N]` reads "`a` is somthing that can be indexed (an array), where the maximum valid index is `N` (you can only access up to address `N-1`, mind), and when you do so, you get a double." Another example: `void *pointers[5]`: "`pointers` can be indexed up to `5`, and doing so returns something that when dereferenced gives you `void` (you can't _actually_ dereference a void pointer at runtime, but if you _could,_ you'd supposedly get `void`)." Also, `char (*array)[42]` reads "`array` can be dereferenced, which gives you something that can be indexed to give char (max index 42)." Finally, `void (*print_function)(char *message)` means "`print_function` is something that can be dereferenced, yielding somthing that can be called (a function), which takes a single argument - given the optional name '`message`' - which can be dereferenced to give a char, and returns nothing (`void`)." Of course, function pointers don't actually need to be dereferenced to call the function they 'point' to, but the `*` differentiates between function pointers and ordinary function declarations. Having said all that, I agree it's kind of weird, and could be avoided if C used different syntax for declaration (new languages probably should).
Great video. I love that you explained how it is said in english and wrote it out. I think that helps soo much when learning a language. and the visuals also another chefs kiss. Great work!
The only thing i missed was WHY you would use pointers. I have no clue and would love to learn. This sounds just like same variable has different name, sounds more confusing to use than anything else.
@@AndrewTSq why do we use street numbers? also, he explains it in the last part of the video. have you watched it? you cant just "pass variables to functions". either you pass the object itself by value, or you pass the address where it is stored in memory. what's difficult to grasp?
@@itellyouforfree7238 to see where we are? and if we are at the right address? Do you mean pointers are to get a variables memoryaddress? but why would you want to use that instead of just using the variable?
As a college student who is learning linked list, stack, queues, trees, graphs, hashtables without a prior knowledge of pointers, i see this as an absolutely good video
The thing that always bugs me about pointers in C++ isn't complexity or their memory side effects, but the symbols, I know what everything does, but I always confuse the symbols because & has at least 3 different functions as a singular symbol depending on where you put it (bitwise AND, make a variable a type reference, or a get reference operation) as does * (multiply, make a variable a type pointer, or a dereference operation) and it makes reading the code for me a super pain in the ass. I'm totally comfortable with pointers, I just hate the syntax for them.
@@po1sonseede9001 Yeah I bet, other stupid thing that makes it doubly confusing in C++ is that neither of those symbols apply to the statement as a whole, only to the identifier, so instead of writing: int* p_1, p_2, p_3; you gotta write: int *p_1, *p_2, *p_3; even though an overwhelming majority of cases you will have multiple pointers being declared at the same time. Conventionally you would see int* as a type, but for some reason in C and thus C++ int is the type and the *p_1 defines a modification to the type exclusive to the identifier that isn't shared with any other object declaration in the language. Only contributing to C/C++'s anti-intuitive nature.
@@po1sonseede9001 Yeah, everyone keeps trying to copy C/C++ in such a manner that makes it still a pain in the ass, I wouldn't mind new languages taking a lot of the clean parts of C++ and implementing them in a more readable fashion, but for some reason instead we get Rust and Zig where they try to retain a high amount of C comparisons but you need to declare the variable and then the type alongside all these other things that honestly just feel like a snub at C and C++. Like why are we going back to pre-ALGOL mathematical type specifications? In almost every case the type is necessary information and you still need a structure to a declaration of variables, its cleaner to integrate the type into the declaration then making it look like an addon to the declaration. Its even uglier for functions.
I want to add, for people trying to understand why the * usage is different when by a type. It's not. The asterisk just isn't by the type, its by the name. int * x; is not saying x is an int pointer, its saying that dereferenced x is an int. This helped me immensely when I realized it, and it explains: int * x, y; makes x a pointer and y an int since y isnt dereferenced but x is in the declaration.
Thanks for the video. I learned the basics of programming from PLT Scheme and became proficient from Python. I've been trying to learn C and I have a decent understanding of the concepts of pointers and addresses, but was struggling to understand why we need to pass pointers to functions instead of the object itself since that's something Python handles for you in the background. I want to take advantage of the power and speed of C, though, so this is very helpful.
I'd find the following much more intuitive: *int px = &x ;because it primarily a pointer int y = (px) ;like in some asm languages (indirect access) But I guess that ship has sailed, at least in C language. Thanks for the video.
A word of caution. You may be tempted do void* or char* cast your pointers to get past some funky type casting foo, but be warned, if you wish to enable compiler optimisation, it will refuse to optimise code that's be obfuscated (to it) this way. It need to have concrete, validatable frame pointers for the variables. It's not stupid and will fail on a void* and in cases where it sees you casting a char* back to a somethingelse* it may fail too. I say "caution" as fixing this later in any size of code base will ruin you month.
- int isn't necessarily 4 bytes, do not ever assume this, use int32_t if you want 4 bytes - using p as a prefix is not a good habit. it originates from a misunderstanding how hungarian notation works. it doesn't add anything, we have had editors that can show you types for years and years now - the age example misses the point that modifying a copy wouldn't do anything - stuff that goes onto the stack is NOT static. it is automatic. static memory either uses the static keyword within a function or is defined outside a function. also an automatic allocation doesn't need to have a statically (at compile time) known size, VLAs do exist
A small tip: Change the font you're using in your video. I know, might be weird to hear, but the ; symbole looks so weird, it makes the code look more complicated. I understood pointers years ago and when i saw your code, i was legit scared of it and thought, i forgot something important lol Or sometimes it looks like a " i " and i thought: Yo where is "xi" comming from
The best explanation of pointers I ever saw was in Hancock's 'The C Primer' first edition only. I never saw it in any other book on C, and I read a lot of them.
I've never found pointers to be all that difficult. This may well be the result of learning PDP-11 assembly with its register addressing modes before any high level languages that supported pointers.
To be fair, in assembly the ONLY way to read/write things in memory is using a pointer, you have little other choices. Assembly programmers should be fluent in using pointers.
@@SerBallister Assembly programmers also understand that types don't exist and pointers are literally just integers, which is imo what makes the most difference.
I don't remember them being that difficult, either. But I have been writing software for quite some time, now. It's possible they were, when I was learning. What concerns me is that people now seem to want to write code without actually understanding what the machine does with it. That's how you wind up with buggy, vulnerable, bloated and slow software. Of which there is a great deal.
@@fghsgh That comes with a down sides though, people make false assumptions about the languages. In C/C++ pointers aren't just integers and types are very real, to the point where you very easily invoke undefined behavior. People think of C/C++ in terms of assembly when the two have nothing in common, they target an abstract machine, not your hardware.
I have been using pointers for a whole ass year now in a VR Company and I never understood them fully (just the basics) it just worked. I had to mix some of the options to see if it gave an error. Lol thanks
I think the issue has always been squarely down to the way they are used in c. You cannot intuitively infer what a * or & means if they used terms like addressof instead people wouldn't get so confused. But its like that because only a few ascii symbols were available at the time and so that is the way that it is. If you start by programming a simple micro controller using assembly its gets hard quickly, you basically need a higher level language to take care of branching and addressing memory - when you come at it from that angle it makes 100% sense to the point where you almost invent the need yourself - only to find c has your back. If you don't use c at least monthly you forget the syntax and thats when we get into the stabbing * or & in because we know its one of them of some form. Efficient code uses pointers because its much faster to point or reference data than to keep moving it. The downside is that since an address is just a number you can very easily point to memory that isn't what you intended. Even the best programmers can easily get caught by an edge case - so there's a trade off between efficient and safe code - i.e. you can spend 20 instructions checking the bounds and 1 instruction copying data to be safe but thats inefficient, so it depends on what your doing. By far the largest confusion for students are strings, char arrays, pointers to, const char arrays and when and which to use - discussion for another day.
A pointer is simply using the index of the memory to find the start of a variable. Like pointing to row 3 in a Excel spreadsheet. Or pointing to row 3 in a database table. & is used to dereference, that means digest the jargon in memory and interpret it as the variable type that is declared for the pointer. Because you could read the stuff in memory as an int or a char, but won't make sense in every context. I hope that helps someone. Pointer variables hold the memory value at its index[0] of all memory that holds a variable. I'm going to pass you something that starts at the memory address in the stored in the pointer variable. In that starting memory location declared as this pointer, don't worry about reading out how big it is yet for now, this is where it starts. I'll tell you how to use it later in the code Mr. computer.
I've been programming on the 6809 chip where pointer indirection is built into the instruction set. To me it's clear and makes sense. However I get super confused as soon as I try to apply that understanding to C or C++.
I was very fascinated by the pointers concept when I was studying it. When I studied its application in Linked List, I was so amazed to see its applications. The concept is just amazing.
this video helped a lot! there were some external quirks i didn’t quite understand because i am an absolute novice at c (ex: i didn’t even know what “->” was for) but this video made the concept very approachable.
While pointers as a concept is easy, I think it's rather the C and C++ syntax that creates most of the confusion. Even the 6502 has few addressing modes that use pointers, and they weren't that hard to understand when I was learning them.
What may be worse is that C++ reads RTL and C reads LTR. const char* x in C is a constant character pointer, const char* in C++ is a pointer to a character constant. Lol
Mate you lost me at 06:11 , suddenly it did not make sense. I'm still at the basics of learning C, so will revisit this often. But seriously thank you for simplifying the concept of pointers and how to visualize them, it really helped.
In C, everything is passed by value(copy). If you pass a struct instance and trying to change it in that function, you only change a local copy of that struct instance. The 'original' copy from caller is untouched. That's one of fundamental reasons using pointers.
Excellent, thanks. I am a Java dev and the dirty little secret about Java is that it DOES use pointers, but the implementation and management of them is hidden from the user. The downside of that is we aren't used to having to think about it so stepping over into the world of C/C++ becomes challenging because of this.
Personally, I didn't have much trouble understanding the concept of pointers and how to use them in C, but a lot of people get thrown off by the fact that the * doubles (pun not intended) as both a type-specifier for a pointer (in an expression like int* or char*) and the dereference operator (in an expression like *p += 1)
Copying from another one of my replies, That's the beauty of it, try formatting your code like int *foo; This basically means foo is a pointer, and you can access the value with *. It also reduces confusion with int *foo, bar; Here bar is an int, foo is an int pointer. This would be a lot more confusing if I wrote it as int* foo, bar; which'd make it seem like int pointer is a type, and foo/bar are instances.
@@shrinjoy1352 no they should not your advice is very discouraging, if you want to understand something the only way to do so is with repitition watch this video 20x times and if you still dont get it find another way if you really want to learn something it wont matter how long it takes
int x = 4 (initializing the value) int *px = &x (set the address of x as the value of pointer px) int y = *px (dereferencing pointer px and set the value of x as the value of y)
I only learned about pointers when I learnt my second language, Rust. I never actually had problems with pointers that much (or Rust really just calls them references, when you say pointer in Rust you are normally referring to a raw pointer.) The syntax is just so easy to understand! And it automatically dereferences for you
References also exist in C++ and are not the same as pointers. There's the auto dereferencing you mentioned and also you can't reference another reference, while you can have a pointer to another pointer.
@@waynezor in rust references reference other references all you want... although you don't normally have much reason to. To me references have always just been raw pointers but they have guarantees about mutable aliasing (and auto deref). Casting a reference to a raw pointer in rust is a NOP I believe. Does C++ have the same no mutable aliasing guarantees?
@@VixieTSQ Let me know if i'm wrong but in Rust you can't have two pointers to the same address because of the one owner rule, when you points to another variable address then the original variable loses the context and dies.
@@sudovon6531 pointing != ownership. With rust references you can either have multiple immutable reference or one mutable reference to one value. But pointers in rust are diferent and not commonly used. They require an unsafe block to dereference because you can do whatever you want with them. You can delete all the pointers and let the value leak. You can delete the value and dereference a null value. It's scary stuff.
Yep I was wondering if I missed it. I've looked up ** and its simply a pointer to a pointer. So you treat it like nested pointers. Ex: int myInteger = 7; //assigning an integer value of 7 to myInteger int* myPointer = &myInteger; //assigning the address of myInteger into myPointer int **myPointerToPointer = &myPointer; // assigning the address of myPointer into the myPointerToPointer. printf(myInteger); // prints out 7 because the value of myInteger is 7 printf(*myPointer); // prints out 7 because the value at the memory address myPointer is pointing to is 7 printf(**myPointerToPointer); // prints out 7 because the value at the memory address pointed to by the memory address myPointerToPointer is pointing to is 7 (myPointerToPointer ->myPointer->myInteger) I know this video is over a year old but I hope this explanation helps someone
Holy shit... pointers took me a few week to understand, and i still don't think i completely understand it. YOUR explanation is just... _chefskiss_ THANK YOU very frikkin much
If only you had made this video 2.5 months ago. My students really could have used it. As you know, only the most dedicated will ask for help. The less dedicated will either read up on bad internet ressources (looking at you, geeksforgeeks) or not try at all and blame me for failing. Seeing how many quit the exam early, a good ressource like this would have been needed. The K&R C book is great and all, but not very compact. One thing missing from the video is the meaning of "pointer + x" and difference to "pointer + pointer". Some groups had the following code in their homework: "unsigned int n = pointer1 - pointer2;". It took me forever to explain exactly why this is not a good idea. Also, thanks for putting the "*" on the right side. "int *p;" vs "int* p;" also takes a long time. Thanks, 90% of the internet for doing it wrong. Only thing that I really don't like about the video is that you wrote "(NULL == heapMemory)" instead of "(heapMemory == NULL)", but that's a matter of preference, I guess.
I think the biggest source of confusion is the syntax and why we need to specify the data type when declaring a pointer. Very often, I see people explaining pointers by emphasizing where the data begins (i.e. the address) but not where the data ends!
That's because pointers have very little care for where the data ends that on you to manage. at best a pointer will use its type to figure out the end of the first element but that feels more like syntactic sugar in C. it will quite happily ignore it if you even so much as implicit cast
@@LostSendHelp_YT the rule of thumb is “try not to start any new project in C language” Hopefully, Zig will get mature enough to not make that a big problem
@@ooooooooooo9656 C is the standard at NASA, and they are still writing C. Rust is illegal at NASA until you can remove the borrow checker. Zig would be a possibility.
@@hugo-garcia In memory each pointer is just an address, so the address of the struct. The pointer would be the address of the first element of the struct (because a struct is essentially its members lined up one after the other in memory (if you ignore padding), so to access the members, the compiler only needs to jump the needed amount of bytes forward to get the address of the other struct members)
@@hugo-garcia A struct is created with a given size depending on what it contains. For example, a struct containing 2 4-bytes integers would be 8 bytes long. Hence this struct would take several addresses in memory, two if we're using a 64-bits (or 4-bytes) OS. When you dereference that struct, you get a pointer to the first address in memory that the struct is stored at. The same thing happens with arrays in C. For example int array[16] declares 16 contiguous addresses in memory, and yields a pointer to the first address of that array. That's how you iterate over an array in C, you start at the first address, then access to the second element with an offset of 1 byte to the first address, etc
One remark. 3:50: Not next to the type, just nest to variable name: If you write int* a, b; you'll get pointer a to integer and integer b. Beside that pretty good material
One of my computing professors, who was quite eccentric, used to like to explain pointers using a quotation from Alice Through the Looking Glass: "You are sad," the Knight said in an anxious tone: "let me sing you a song to comfort you." "Is it very long?" Alice asked, for she had heard a good deal of poetry that day. "It's long," said the Knight, "but very, very beautiful. Everybody that hears me sing it-either it brings the tears into their eyes, or else-" "Or else what?" said Alice, for the Knight had made a sudden pause. "Or else it doesn't, you know. The name of the song is called 'Haddocks' Eyes'." "Oh, that's the name of the song, is it?" Alice said, trying to feel interested. "No, you don't understand," the Knight said, looking a little vexed. "That's what the name is called. The name really is 'The Aged Aged Man'." "Then I ought to have said 'That's what the song is called'?" Alice corrected herself. "No, you oughtn't: that's quite another thing! The song is called 'Ways And Means': but that's only what it's called, you know!" "Well, what is the song, then?" said Alice, who was by this time completely bewildered. "I was coming to that," the Knight said. "The song really is 'A-sitting On A Gate': and the tune's my own invention." en.wikipedia.org/wiki/Haddocks%27_Eyes#:~:text=The%20name%20of%20the%20song,what%20the%20name%20is%20called.
wanna learn more about C? check out my courses at lowlevel.academy (get 20% off)
It's easy. Just add or remove asterisks or ampersands until it works.
* is the inverse function of &
Y= * px = *&x= x; // y= x
Working with pointers is easy af... Just try different permutation and combinations of & and * until code works like u wanted it to work... Don't complicate easy things.. xD 😁😁
Next thing you know it, you created a buffer overflow attack
@@tenseikenzx-3559 And that's why we use Rust
This is wrong in so many levels 😂
Me after 20 minutes of compile time errors:
__asm__
{
MOV DWORD PTR [0xDEADBEEF],%EAX
}
@@dakata2416 no. that's why we use unique_ptr or shared_ptr.
One important clarification. The asterisk(*) is an attribute of the variable not the type which your explanation seems to suggest. This distinction is important because if you consider the following line:
int* x, y;
x is a pointer to an int while y is just an int. If you wanted both to be pointers you would need to write something like:
int *x, *y;
So i should do int **pX; instead of int** pX; as a good habbit
@@FriedMonkey362 It's up to you. That is how I prefer it as I feel it more accurately reflects the syntax, but Strourstrup (founder of C++) actually prefers it *int* pX;*. There is not "right" way per say, so do what you think makes sense : )
That makes sense : *pX (value pointed by pX) is, indeed, an int.
but int * x, y; is just a syntactic sugar to condense on one line this:
int * x;
int y;
during declaration phase the * operator is treated like the type of memory you'll allocate, otherwise it becomes a unary operator to dereference pointers.
so when you declare variables it actually makes sense to read "int * x" as "x is a pointer to int" and otherwise, seeing "*x = y" as "assign y to the address pointed by x"
@@FriedMonkey362 yes as a good habit 👍🏼
C++ was the first language I learned.. and I only spent a short time with it. But one thing that made all the difference was having a mental model of computer's memory with addresses and values. Before I knew to do that, C++ was incredibly frustrating. This video is smart to lead with that lesson.
Any resources on learning how computers handle memory?
Same, I taught myself C++ well over a decade ago at the wee age of 12 and it took me near 2 years to get pointers. I remember what finally made it click was an analogy comparing it to actual mail addresses, will never forget that enlightening moment.
@@imt3206 in my case, learning how computers handle memory is automatic with learning pointers and data structures like array, stack, qeue, linked list. especially linked list, that shit opened my eyes how linked list is so much superior than array in most cases
ua-cam.com/users/shorts2YCtH5_56po?feature=share
ua-cam.com/users/shorts2YCtH5_56po?feature=share
I'm a senior majoring in Computer Science at college. If you're a young person whose looking to learn about programming and computers, keep watching this guy's stuff! All complex systems can be broken down to simpler parts. That's what this channel does very well when explaining complex concepts like pointers. This is the first video I've seen but I'm definitely subbing cuz this guy not only knows his stuff but more than I do!
My college experience was incredibly lacking in low level courses, which I imagine will be the case at many other universities in the coming future. High-level problem solving has it's place, but low-level is important because a house won't last without a proper foundation. The foundations of computer science are the most important area to master, arguably more important than programming itself.
Don't be a cog; be the future.
What programming languages were pushed at your college? My college is pushing C++ right out of the gate and forces us to learn Assembly as well. Is your college similar?
love this
@@coolperson4582 What college? You're lucky, enjoy!
@@coolperson4582 You are so lucky, my university enforces java and eclipse. It feels like oracle is lobbying there.
@@coolperson4582assembly in 2024?
Understanding references, pointers, smart pointers and memory is gamechanger and is crucial thing to know. Dont give up trying to understand, it is well worth it and with bit of practice becomes normal to read and understand.
I regret giving up programming because of this at school, it would have boosted my career as software engineer forward by years had i put more time into it.
But can’t find practice problems online. So far being working with this company for about 7 months and everywhere in the codebase we use pointers and I just get more confused especially when a pointer or reference is passed to a method and returned from a method
@@abdiasisibrahim5903 best practice i got was when i tried to make my own simple tile based farming game, so i suggest trying to create something of your own, and when problems arise you need to understand and solve them.
I didnt ever finish it, so i cant really show how code looks like, but one of many problems i had was how to grow plants, which I resolved by creating timer, to which I subscribed selected plants and called grow method on them when timer said it is time. Problem also included how to unsubscibe them correctly.
Another issue arised when my game grew too much and I had to split it in smaller modules, so eventually I needed to separate drawing routines from game logic. I remember it being tricky, as my game directly extended from engine.
I stored tiles and other assets in raw arrays stored at heap, so it also needed some thought to put into.
Such practice directly tests your knowledge and teaches you a bit about design patterns and how memory and language works.
Making game trainers is a great way to learn about pointers
@@zanityplays how do you make game trainer (sorry I’m not a gamer)?
@@abdiasisibrahim5903 you use a memory searching tool such as cheat engine to find interesting in game stuff such as player health, some debuggers also have this functionality. Then use relevant os APIs to retrieve a handle to the process and modify data at the found addresses
I struggled quit a bit with pointers and references back when I was learning C (my first programming language,) but I did not gave up and eventually managed to understand them. They're so simple, yet so powerful, and open up an almost infinite number of possibilities. Sometimes, I managed to break programs when using pointers, but in general I have no problem using them 😄
I really lost hope to learn the .. i do find mathematics and electronics are more easy 🤦♂️🤦♂️
can you help me with this, i on to writing a leetcode problem of merging two sorted list, and cant understand understand this line,
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
}
will you please explain, i had wasted probably 2 hours and still cant understand..
The best tutorial so far. This is what high lever languages do all the time with "references" which is just a pointer bound to a value but you cant play with the pointer directly only the value he is pointing too.
I don’t fully understand everything, but you make me feel like I will one day…and that’s the most important thing I enjoy the most! It’s all about the journey of learning and not always to the final destination! Thank you for this content!
How is it going man?
i actually appreciated pointers more when i started to learn golang! it really helps especially when you don't always want to expect a return type when making a function and just modify a value that you pass into
Yes, that's called passing by reference, and it's a very useful feature in many languages to save function call overhead and to return multiple results from a function.
Yep! Acknowledging the difference between pass-by-value and pass-by-reference is quite important, and it helps a lot to deeper understand a language.
One decent example can be seen in Visual Basic (just the first one that came to mind), where a methods are assigned a role: either a subroutine (no return value) or a function (has a return value). The function/subroutine parameters can also be prefixed with “ByVal” or “ByRef” depending on what you are going to do with those arguments. It’s quite flexible, but sometimes a bit difficult for some to understand
yep, Go is awesome
@@gg-gn3re I wholeheartedly agree :)
I’ve been programming for years and I still feel like this video flipped a switch in my brain. Excellent, I’m going to bookmark this
Video idea: How malloc() works and how does it know what memory is considered "free to use". I started programming on retro game consoles where you know ahead of time exactly how much RAM you have at your disposal, so allocation functions in general are very "alien" to me.
malloc doesn't know. The OS knows.
I figured as much since MS-DOS had a "malloc" feature where you would tell it how much menory you needed and DOS would tell you where it is. But how does the OS know then?
it probably uses mmap or sbrk
@@williamdrum9899 Why wouldn't the os know? That's one of the core functionalities an os provides
@@williamdrum9899 it's still the same on any OS if I'm not mitaken.
The OS has a map of available memory blocks allocated to your program (called pages). When you call malloc, which is a system call, the OS finds a contiguous space of memory allocated to your program where the size you asked for would fit. If not enough memory is available in your page, a new page is allocated to your program.
About to finish my computer science degree, and I never really understood pointers because most modern languages abstract this. It's nice to make a full circle though.
Thanks!
Understanding isnt hard, applying it cleanly is. Working by bypassing scope might be faster but the need of keeping track of it is hard lest one gets memory leak. Not to mention in bigger teams having to rely on coworkers to apply it cleanly. It becomes a cascading problem with less avenues to debug such bugs.
edit: 1yr on seems my post got some traction, I want to add something. One of many uses and evolution of a Computer is to be a better Calculator. To that end, computers must be able to provide to a user mildly complex logical constructs/objects on which mathematics can be applied and work on them e.g. plus symbol signifying Concatenation of String objects. One should be able to develop some function without having to think of this and that memory allocation. Usage of pointers should only be approached by the top 1 percentile of experienced devs who is probably designing a solution for other devs; or embedded devs having to work with low level resources but won't have a cascading problem.
That's why we practice! :D
@@chudchadanstud then don't put noobs on your dev team
@@_khaine You can put me on your dev team
@@chudchadanstud not naive at all
Exactly, all these videos explain the concept well, but the real problem is when you are coding something and you dont really understand why you need to use a pointer
Thanks! This is the most explanatory and easy to understand video about pointers so far! I've been writing code for ages and never really wondered about how pointers work. Just started with C and your video really helped.
The
int *
can be looked at as the type - it's a pointer to an address space sized to fit an int; bear in mind that different machines or different compilers/options can have different size ints, and declaring that size will let the compiler generate binaries allocating the right number of bits of memory.
this comment touches on something i REALLY hate about C. as far as I'm concerned, char is a fundamentally different type to an char*. which, it is. they're a different size and everything. so WHY can we write declarations like "char a, *b;" creating two variables of fundamentally different types in the same statement? it's stupid and i hate it.
@@SoulSukkur back in the old days people couldn't type very well. And monitors were very low resolution, limiting the number of characters and lines visible. So characters had to be conserved.
@@SoulSukkur nobody is forcing you to write it like that
@@SoulSukkur i just don’t use multiple-declarations, they are already ugly by themselves.
3 min in and I straight up subscribed. The code translation into english is exactly what makes this so easy to learn.
Thanks a lot.
I subscribed at 4 min.
I first learned about pointers while trying to make Whack-A-Mole with an Arduino. I wanted to pass a “mole” struct into a void function to mutate it, but couldn’t figure out why it wasn’t working… wish I’d seen this video back then; it would’ve saved me several hours of confused googling lol
5:13 You can also say that if there was no asterisk, you would put the value of the pointer pX, which is a memory address, to the variable Y. You want the value of that memory address, so you put the asterisk there.
> _"if there was no asterisk, you would put the value of the pointer pX, which is a memory address, to the variable Y"_
which would cause issues
@@yash1152 why?
@@proloycodes i dont remember the specifics, try compiling with the compiler flags _-Werror -Wall -Wextra_ and see, it will tell you.
I’ve never really used C so i’m more familiar with the newer languages masking this functionality. Listening to this video is really easy to absorb. Honestly if you can show more examples of pointers in a part 2 i think someone could really solidify the knowledge quickly!
dog
@@danielacevedo7539 ong dog fr slay kween
The concept of a pointer is the easy part. The difficult part is from 6:00 and onwards.
thank you so much professor, you taught me something in 8 mins!
Happy to help!
@@LowLevelTV hi
I am seeing your videos from a week I noticed that your explanation made all our ways clear in doubts but I have a question in this pointers topic on embedded c ?
The question was why pointers don't use in embedded c
Can you pls clarify the following questions with your explanation I had this doubt after watching this pointers topic in your channel...
@@ramakrishna4092 Rama, here's an answer to the common question "why we have to use pointers in embedded C". If you use the Pico/RP2040 SDK, you have to use pointers, the functions in the SDK demand that, and I think it'd be almost impossible to code for RP2040 in C/c++ without the SDK. As LLL says at 6:44, I figure the RPi programmers used pointers to get around scoping issues. They had to do it this way, so we do as well.
You think you understand pointers now? Then make sense of this type: int (*(*f())[13])()
@@mircopaul5259 wtf is that, lisp?
I found pointers inheretly easy to understand when i was learning them, what can be hard, for me at least, is how to implement them in an effective way. I can understand the difficulty, since it involves computer memory.
Great explanation, i think the reason why pointers are so widely misunderstood or hardly understood is the lack of explanation regarding memory layout (which you explained really well) and the not so intuitive syntax
Glad it was helpful!
@@LowLevelTV umh, not to shoot you down or anything, but if i were being honest, this was like basic stuff. it's fine. the real problem i face is with 2D arrays, and passing them to functions.
the one you explained was just plain variables - it was not at all hard for me. even 1d array is managable, but i can never get pointers to work with 2d arrays, and i thought u'd cover those too....
@@yash1152 Well arrays decay to pointers but it's only the top declarator that does so. A 2d array hence decays to T(*)[N]
I didn't know what a pointer is but this video is so clear it makes perfect sense. I've watched hundreds of videos over the months and yours are some of THE best. Well done, and much appreciated.
i have found that sometimes when i am really, *really* struggling to understand a concept it might simply be a product of obsessively trying to understand it, so your looking at like 50 interpretations of what a function is and bombarding your brain with too much information for the actual concept to have any cohesion. i remember reading that the best way to remember something is, well, i am going to inject the first part 1. apply what you learn to something you care about 2. repeat it [use it] 10 times in a row
The thing that was the most confusing for me was the syntax and all of it clicked when you simply explained that the star is used for two different things. I just couldn't understand why star next to type is a pointer but star next to variable is a value under the pointer
" star next to type is a pointer but star next to variable is a value under the pointer"..
Exactly! I think most tutorials seem to fixate on the memory map element of pointers, which imo isn't that hard to understand. It's the subtly contradictory notation that's that actual source of confusion for most.
Yea, assigning too many uses to the same symbol creates confusion. The concept is easy enough to understand, the grammar is not.
4:32 this line is extremely helpful
Great video, but I think it required more examples of the applications of pointers. Beginners tend to have a small scope of the concept of pointers with a simple explanation. But honestly to me, pointers can never be explained. Its concept and applications can only be truly understood once we've experimented with it hahaha.
Noted!
It's C's equivalent of "no one can explain what a monad is"
Exactly. All I need is to see use cases.
Basically if you want to pass a huge struct to a function , instead of copying the whole thing in (ie via the copy by value parameter), pass it in by pointer/reference. Of course if you modify the struct in the function it modifies the original.
@@napalm5 heh.. that explanation is what I was searching for, thanks
Honestly the best video I have ever seen on the pointers. Great work!
u know arrays, right? well, all of memory is an array. a pointer is an index of this array. yup, thats it.
Basically yeah
using a double pointer to create two dimensional structures(rows, cols) has been one of my favorite things to learn in college so far, and it goes deeper when you figure out you can create other pointers to increase the size it gets crazy
I really understood pointers when I got into embedded programming, where you have to access builtin memory address (registers), read their state or write to them. But wait until you get into typecasting pointers, that gets really fun.
every variable can be a char array if you're brave enough.
@@SoulSukkur you can swap bytes by casting variables into char arrays
And also doing dangerous thing like this is allowed in embedded C bare metal. pointing to random memory.
uint32_t *random_mem = (uint32_t*)0x200800FF;
*random_mem = 0xEF; //cause weird behaviour or hardfault.
Watching this before my C++ exam, was stressing hard bc it’s all pointers. It’s so easy now! Thanks bubba
If you have an array of structs, a pointer would be like passing the number inside the brackets, like array[0] or array[3] etc. As C pre complies everything in to tetris blocks repeated at a fixed interval, as each struck inside the array are 12bytes in size (example), so now you can refer to struct members with and offset of 0 to 11, you just pass base number to the functions, an absolute address in memory that is the base number to each "apartment block" and that is called a pointer.
6:00 I use the verbalisation for *pX as
"value at location to which px points"
Or generally
"Value at loc. to which points"
0:12 I only just started learning C++, but I figure pointers are probably the best part of the whole language, and I'm super annoyed that I wasn't able to read an integer as a string using them, I asked someone who knows more about it than me and they said that Windows doesn't want people doing that kind of thing, something like "That could break your computer irreparably if it was allowed," or that I would need Windows Pro instead of Home to do it, what does Windows know about what I want to do with my device? Bogus! If only Windows didn't have corn cob up their but and would let us directly alter the byte tape, it would be most ideal if there was a BrainF interpreter/compiler that used the actual byte tape instead of just a simulated byte tape that is stored on the actual byte tape to keep things safe.
I dont quite understand why you are talking about byte tape and stuff... but you totally should be able to cast a integer pointer to a string pointer, if thats what you mean. Not that its a good idea lol
@@BetaChri5 Sort of what I want to do, but I don't want it to just make an integer 32 become a string "32," that's boring. I want it to rip the binary representation of the integer out and into a string instead. Without any conversions behind the scenes. Not even adding a null pointer to make sure that the string has an end to it.
Thank you for the explanation! Pointers took me about two years to be able to use them, but I legit just never understood why, other than that we could manually delete them as needed. Never understood why my code would work or not work with or without pointers, but understanding the static and dynamic part really helps
I come from the field of PLC programming. Until recently you could only program most PLCs with either a graphical programming language (good for logic tasks) or in assembler of the PLCs processor. (Good for data tasks).
Pointers were really to only way to implement a loop with a pointer iterating over a given field of data.
The good thing is pointers and memory handling are really easy in PLCs compared to PCs, so learning pointers there was a good start.
I learned to program PLCs in tech school about 3 years ago. I tell you this RN, my instructor would've thrown me out on my ear if he ever saw a pointer in my code. He nearly did so when I found the JMP command all on my own, especially after I (mis)used it and created an infinite loop. Apparently, not even he used the JMP instruction regularly in some 15 years of PLC coding, so he was in no position or mood to look at my code, see that there was a JMP going up the ladder instead of down, and correct it before problems arose.
getting LabView vibes
@@mage3690 Haha lmao
Pointers in x86 asm aren't terrible. Basically it's just passing an address for some data as an argument. Where it would trip me however is just the way it looks in C. That is going to take some getting used to.
Before I did week 5 of CS50 I had the impression that complex data structures just need arrays/lists and that’s it. But now I realise how bloody amazing these things really are. The fact you can link multiple things together all using pointers was such an eye opener when it comes to programming.
I learned pointers by starting out with JS, then learning about how computers work on the low level, then learning cpp, and trying out pointers. By then it was relatively intuitive lol
that may be because JavaScript doesn't have pointers
Thank you. My professor is making a huge deal out of pointers and how difficult they will be, but with this video, they seem to be fairly simple and useful. Thanks.
I think what caused the most confusion for me regarding pointers was when using * as the indicator that a variable was a pointer and using the same symbol to de-reference.... I think it would have caused much less confusion if we didn't use the asterisk for both
> _"* is both the pointer declaring and dereference operator.... much less confusion if we didn't use the asterisk for both
"_
yeah, i totally agree
Change the spacing and it makes more sense.
Func(int *pX)
{
int y = *pX;
}
@@protox4 no, it doesn't
(int *) - type of pointer, that points to integer number
* - dereference operator
they're absolutely two different things
@@dadoo6912 it's to do with the whole idea of "declaration follows use". The asterisk is on the variable name because in some weird way, it acts as the dereferencing operator within the declaration.
Something like `int *pX` really means (in terms of the declaration semantics) "`pX` is something that can be dereferenced (i.e. a pointer) and when you dereference it, you get an `int`."
Similarly, `double a[N]` reads "`a` is somthing that can be indexed (an array), where the maximum valid index is `N` (you can only access up to address `N-1`, mind), and when you do so, you get a double."
Another example: `void *pointers[5]`: "`pointers` can be indexed up to `5`, and doing so returns something that when dereferenced gives you `void` (you can't _actually_ dereference a void pointer at runtime, but if you _could,_ you'd supposedly get `void`)."
Also, `char (*array)[42]` reads "`array` can be dereferenced, which gives you something that can be indexed to give char (max index 42)."
Finally, `void (*print_function)(char *message)` means "`print_function` is something that can be dereferenced, yielding somthing that can be called (a function), which takes a single argument - given the optional name '`message`' - which can be dereferenced to give a char, and returns nothing (`void`)." Of course, function pointers don't actually need to be dereferenced to call the function they 'point' to, but the `*` differentiates between function pointers and ordinary function declarations.
Having said all that, I agree it's kind of weird, and could be avoided if C used different syntax for declaration (new languages probably should).
Great video. I love that you explained how it is said in english and wrote it out. I think that helps soo much when learning a language. and the visuals also another chefs kiss. Great work!
One of the best explanations I have seen so far
Okay what what is THE best one you've seen ?
The only thing i missed was WHY you would use pointers. I have no clue and would love to learn. This sounds just like same variable has different name, sounds more confusing to use than anything else.
@@AndrewTSq why do we use street numbers? also, he explains it in the last part of the video. have you watched it? you cant just "pass variables to functions". either you pass the object itself by value, or you pass the address where it is stored in memory. what's difficult to grasp?
@@itellyouforfree7238 to see where we are? and if we are at the right address? Do you mean pointers are to get a variables memoryaddress? but why would you want to use that instead of just using the variable?
As a college student who is learning linked list, stack, queues, trees, graphs, hashtables without a prior knowledge of pointers, i see this as an absolutely good video
The thing that always bugs me about pointers in C++ isn't complexity or their memory side effects, but the symbols, I know what everything does, but I always confuse the symbols because & has at least 3 different functions as a singular symbol depending on where you put it (bitwise AND, make a variable a type reference, or a get reference operation) as does * (multiply, make a variable a type pointer, or a dereference operation) and it makes reading the code for me a super pain in the ass. I'm totally comfortable with pointers, I just hate the syntax for them.
Dyslexia makes it worse trust me.
@@po1sonseede9001 Yeah I bet, other stupid thing that makes it doubly confusing in C++ is that neither of those symbols apply to the statement as a whole, only to the identifier, so instead of writing:
int* p_1, p_2, p_3;
you gotta write:
int *p_1, *p_2, *p_3;
even though an overwhelming majority of cases you will have multiple pointers being declared at the same time. Conventionally you would see int* as a type, but for some reason in C and thus C++ int is the type and the *p_1 defines a modification to the type exclusive to the identifier that isn't shared with any other object declaration in the language. Only contributing to C/C++'s anti-intuitive nature.
@@Spartan322 I think what bothers me is everyone wants a C/C++-Like syntax nowadays, completely disregarding if the syntax is intuitive.
@@po1sonseede9001 Yeah, everyone keeps trying to copy C/C++ in such a manner that makes it still a pain in the ass, I wouldn't mind new languages taking a lot of the clean parts of C++ and implementing them in a more readable fashion, but for some reason instead we get Rust and Zig where they try to retain a high amount of C comparisons but you need to declare the variable and then the type alongside all these other things that honestly just feel like a snub at C and C++. Like why are we going back to pre-ALGOL mathematical type specifications? In almost every case the type is necessary information and you still need a structure to a declaration of variables, its cleaner to integrate the type into the declaration then making it look like an addon to the declaration. Its even uglier for functions.
You just don't know C/C++... Dont lie to us and to yourself... 😅
Brand new to C and this made something I've been dreading and "pre-confused" about seem much more understandable.
I want to add, for people trying to understand why the * usage is different when by a type. It's not. The asterisk just isn't by the type, its by the name.
int * x;
is not saying x is an int pointer, its saying that dereferenced x is an int.
This helped me immensely when I realized it, and it explains:
int * x, y;
makes x a pointer and y an int since y isnt dereferenced but x is in the declaration.
THANK YOU! It surpises me how can a teacher introduce this concept without explaining it at university. This was a life saver
Thanks for the video. I learned the basics of programming from PLT Scheme and became proficient from Python. I've been trying to learn C and I have a decent understanding of the concepts of pointers and addresses, but was struggling to understand why we need to pass pointers to functions instead of the object itself since that's something Python handles for you in the background. I want to take advantage of the power and speed of C, though, so this is very helpful.
Awesome I’m happy that it helped!
I'd find the following much more intuitive:
*int px = &x ;because it primarily a pointer
int y = (px) ;like in some asm languages (indirect access)
But I guess that ship has sailed, at least in C language. Thanks for the video.
A word of caution. You may be tempted do void* or char* cast your pointers to get past some funky type casting foo, but be warned, if you wish to enable compiler optimisation, it will refuse to optimise code that's be obfuscated (to it) this way. It need to have concrete, validatable frame pointers for the variables. It's not stupid and will fail on a void* and in cases where it sees you casting a char* back to a somethingelse* it may fail too. I say "caution" as fixing this later in any size of code base will ruin you month.
Wtf man this is way easier than I thought, I was having such a hard time to understand pointers. Love you ❤
- int isn't necessarily 4 bytes, do not ever assume this, use int32_t if you want 4 bytes
- using p as a prefix is not a good habit. it originates from a misunderstanding how hungarian notation works. it doesn't add anything, we have had editors that can show you types for years and years now
- the age example misses the point that modifying a copy wouldn't do anything
- stuff that goes onto the stack is NOT static. it is automatic. static memory either uses the static keyword within a function or is defined outside a function. also an automatic allocation doesn't need to have a statically (at compile time) known size, VLAs do exist
This has to be one of the best channels on youtube. I have been fighting this for so god dam long
A small tip: Change the font you're using in your video. I know, might be weird to hear, but the ; symbole looks so weird, it makes the code look more complicated. I understood pointers years ago and when i saw your code, i was legit scared of it and thought, i forgot something important lol Or sometimes it looks like a " i " and i thought: Yo where is "xi" comming from
Same here, the semi-colon got me confused, needed to back it up a bit to confirm it was indeed just a semi-colon.
True I thought it’s „i”
This is the better video programming content I have never seen, simply insane good.
The best explanation of pointers I ever saw was in Hancock's 'The C Primer' first edition only. I never saw it in any other book on C, and I read a lot of them.
I've never found pointers to be all that difficult. This may well be the result of learning PDP-11 assembly with its register addressing modes before any high level languages that supported pointers.
To be fair, in assembly the ONLY way to read/write things in memory is using a pointer, you have little other choices. Assembly programmers should be fluent in using pointers.
@@SerBallister Assembly programmers also understand that types don't exist and pointers are literally just integers, which is imo what makes the most difference.
I don't remember them being that difficult, either. But I have been writing software for quite some time, now. It's possible they were, when I was learning. What concerns me is that people now seem to want to write code without actually understanding what the machine does with it. That's how you wind up with buggy, vulnerable, bloated and slow software. Of which there is a great deal.
Yeah, I came from 6510 and ARM assembly and never had a single problem with them. Didn't even know the terminology, just used them.
@@fghsgh That comes with a down sides though, people make false assumptions about the languages. In C/C++ pointers aren't just integers and types are very real, to the point where you very easily invoke undefined behavior. People think of C/C++ in terms of assembly when the two have nothing in common, they target an abstract machine, not your hardware.
such a underrated channel holy shid ive never found someone who can explain this good and easy
Great video! Not sure if it's just me, but I would suggest to change font for some of the examples as the ; looks too much like an i
Thanks for the tip!
@@LowLevelTV Song name, pls?
I have been using pointers for a whole ass year now in a VR Company and I never understood them fully (just the basics) it just worked. I had to mix some of the options to see if it gave an error. Lol thanks
I think the issue has always been squarely down to the way they are used in c. You cannot intuitively infer what a * or & means if they used terms like addressof instead people wouldn't get so confused. But its like that because only a few ascii symbols were available at the time and so that is the way that it is. If you start by programming a simple micro controller using assembly its gets hard quickly, you basically need a higher level language to take care of branching and addressing memory - when you come at it from that angle it makes 100% sense to the point where you almost invent the need yourself - only to find c has your back.
If you don't use c at least monthly you forget the syntax and thats when we get into the stabbing * or & in because we know its one of them of some form.
Efficient code uses pointers because its much faster to point or reference data than to keep moving it. The downside is that since an address is just a number you can very easily point to memory that isn't what you intended. Even the best programmers can easily get caught by an edge case - so there's a trade off between efficient and safe code - i.e. you can spend 20 instructions checking the bounds and 1 instruction copying data to be safe but thats inefficient, so it depends on what your doing.
By far the largest confusion for students are strings, char arrays, pointers to, const char arrays and when and which to use - discussion for another day.
A pointer is simply using the index of the memory to find the start of a variable. Like pointing to row 3 in a Excel spreadsheet. Or pointing to row 3 in a database table. & is used to dereference, that means digest the jargon in memory and interpret it as the variable type that is declared for the pointer. Because you could read the stuff in memory as an int or a char, but won't make sense in every context. I hope that helps someone. Pointer variables hold the memory value at its index[0] of all memory that holds a variable. I'm going to pass you something that starts at the memory address in the stored in the pointer variable. In that starting memory location declared as this pointer, don't worry about reading out how big it is yet for now, this is where it starts. I'll tell you how to use it later in the code Mr. computer.
I've been programming on the 6809 chip where pointer indirection is built into the instruction set. To me it's clear and makes sense. However I get super confused as soon as I try to apply that understanding to C or C++.
I was very fascinated by the pointers concept when I was studying it. When I studied its application in Linked List, I was so amazed to see its applications. The concept is just amazing.
Love this kind of explanation!
Glad it helped!
this video helped a lot! there were some external quirks i didn’t quite understand because i am an absolute novice at c (ex: i didn’t even know what “->” was for) but this video made the concept very approachable.
While pointers as a concept is easy, I think it's rather the C and C++ syntax that creates most of the confusion. Even the 6502 has few addressing modes that use pointers, and they weren't that hard to understand when I was learning them.
What may be worse is that C++ reads RTL and C reads LTR. const char* x in C is a constant character pointer, const char* in C++ is a pointer to a character constant. Lol
Excellent! I looked at a couple of other tutorials, but only this one helped me. Thanks!
Mate you lost me at 06:11 , suddenly it did not make sense. I'm still at the basics of learning C, so will revisit this often. But seriously thank you for simplifying the concept of pointers and how to visualize them, it really helped.
In C, everything is passed by value(copy). If you pass a struct instance and trying to change it in that function, you only change a local copy of that struct instance. The 'original' copy from caller is untouched. That's one of fundamental reasons using pointers.
@@MaxwellHay Ohh it makes sense
Excellent, thanks. I am a Java dev and the dirty little secret about Java is that it DOES use pointers, but the implementation and management of them is hidden from the user. The downside of that is we aren't used to having to think about it so stepping over into the world of C/C++ becomes challenging because of this.
Personally, I didn't have much trouble understanding the concept of pointers and how to use them in C, but a lot of people get thrown off by the fact that the * doubles (pun not intended) as both a type-specifier for a pointer (in an expression like int* or char*) and the dereference operator (in an expression like *p += 1)
Copying from another one of my replies,
That's the beauty of it, try formatting your code like
int *foo;
This basically means foo is a pointer, and you can access the value with *. It also reduces confusion with
int *foo, bar;
Here bar is an int, foo is an int pointer. This would be a lot more confusing if I wrote it as
int* foo, bar;
which'd make it seem like int pointer is a type, and foo/bar are instances.
@@casualoutlaw540 Yeah that's a useful formatting tip about keeping the *s with the names.
im not even coding yet
(although i want to) and this is pretty useful
dont call your self low level learning, call yourself high level teaching
who else watched the video and still confused ? 😂
lol same
u should leave cs if u cant understand this
@@shrinjoy1352 no they should not your advice is very discouraging, if you want to understand something the only way to do so is with repitition watch this video 20x times and if you still dont get it find another way if you really want to learn something it wont matter how long it takes
@@HUSS_BOSS I have now even more questions than before video.
@@shrinjoy1352 literal nobody think i should leave cs based on his comment
int x = 4 (initializing the value)
int *px = &x (set the address of x as the value of pointer px)
int y = *px (dereferencing pointer px and set the value of x as the value of y)
I only learned about pointers when I learnt my second language, Rust. I never actually had problems with pointers that much (or Rust really just calls them references, when you say pointer in Rust you are normally referring to a raw pointer.) The syntax is just so easy to understand! And it automatically dereferences for you
References also exist in C++ and are not the same as pointers.
There's the auto dereferencing you mentioned and also you can't reference another reference, while you can have a pointer to another pointer.
@@waynezor in rust references reference other references all you want... although you don't normally have much reason to.
To me references have always just been raw pointers but they have guarantees about mutable aliasing (and auto deref). Casting a reference to a raw pointer in rust is a NOP I believe.
Does C++ have the same no mutable aliasing guarantees?
@@VixieTSQ Let me know if i'm wrong but in Rust you can't have two pointers to the same address because of the one owner rule, when you points to another variable address then the original variable loses the context and dies.
@@sudovon6531 pointing != ownership. With rust references you can either have multiple immutable reference or one mutable reference to one value.
But pointers in rust are diferent and not commonly used. They require an unsafe block to dereference because you can do whatever you want with them. You can delete all the pointers and let the value leak. You can delete the value and dereference a null value. It's scary stuff.
To me this isn't a class on pointers, this is a class on teaching. Mad skills at making everything look simple.
You mentioned double pointers and array pointers but didn't dive into them at all. You should make a part 2 on that.
Yep I was wondering if I missed it. I've looked up ** and its simply a pointer to a pointer. So you treat it like nested pointers.
Ex:
int myInteger = 7; //assigning an integer value of 7 to myInteger
int* myPointer = &myInteger; //assigning the address of myInteger into myPointer
int **myPointerToPointer = &myPointer; // assigning the address of myPointer into the myPointerToPointer.
printf(myInteger); // prints out 7 because the value of myInteger is 7
printf(*myPointer); // prints out 7 because the value at the memory address myPointer is pointing to is 7
printf(**myPointerToPointer); // prints out 7 because the value at the memory address pointed to by the memory address myPointerToPointer is pointing to is 7 (myPointerToPointer ->myPointer->myInteger)
I know this video is over a year old but I hope this explanation helps someone
Holy shit... pointers took me a few week to understand, and i still don't think i completely understand it.
YOUR explanation is just... _chefskiss_ THANK YOU very frikkin much
Semicolon ❌ dude sitting ✅
IT WORKED, THANKS I'VE BEEN LOOKING FOR THIS FOREVER, BUT NO TUTORIAL COULD EXPLAIN IT AS YOU DID
If only you had made this video 2.5 months ago. My students really could have used it. As you know, only the most dedicated will ask for help. The less dedicated will either read up on bad internet ressources (looking at you, geeksforgeeks) or not try at all and blame me for failing.
Seeing how many quit the exam early, a good ressource like this would have been needed. The K&R C book is great and all, but not very compact.
One thing missing from the video is the meaning of "pointer + x" and difference to "pointer + pointer".
Some groups had the following code in their homework: "unsigned int n = pointer1 - pointer2;". It took me forever to explain exactly why this is not a good idea.
Also, thanks for putting the "*" on the right side. "int *p;" vs "int* p;" also takes a long time. Thanks, 90% of the internet for doing it wrong.
Only thing that I really don't like about the video is that you wrote "(NULL == heapMemory)" instead of "(heapMemory == NULL)", but that's a matter of preference, I guess.
Error: segmentation fault (core dumped)
thank you sm this was such a good video covering the basics and clarified concepts that i was unsure of for the longest time!
Great video! Can you give a more advanced tutorial, like using pointers with arrays and functions?
you single handedly solved all my confusion. you are a godsend. thank you.
I think the biggest source of confusion is the syntax and why we need to specify the data type when declaring a pointer. Very often, I see people explaining pointers by emphasizing where the data begins (i.e. the address) but not where the data ends!
That's because pointers have very little care for where the data ends that on you to manage. at best a pointer will use its type to figure out the end of the first element but that feels more like syntactic sugar in C. it will quite happily ignore it if you even so much as implicit cast
Because it doesn't matter where the data ends.
6:49 "malloc failed bruh" 🤣
what an intro brow. Even I didnt watch it yet. Clear to say that Ima question my life
I disagree with the current title, **because *I[] &still[] have() *questions().
What questions do you have?
@@petrifiedpanda2869 i believe he is referring to parsing complicated declarations involving pointers...
This is a beautiful video my friend! I sorta got the concept, but this! This video helped me COMPREHEND it!
NASA said don't use pointers
?
Iirc they said to use references, which are just fancy pointers
@@LostSendHelp_YT the rule of thumb is “try not to start any new project in C language”
Hopefully, Zig will get mature enough to not make that a big problem
@@ooooooooooo9656 C is the standard at NASA, and they are still writing C. Rust is illegal at NASA until you can remove the borrow checker. Zig would be a possibility.
@@LostSendHelp_YT yeah, but average programmer don't be required to make NASA level code.
Really good work bruh!!! Everything is explained slowly and step-by-step, word-by-word
What if your pointer points to a Struct?
The example showing the pass-by-reference shows an example of a pointer to a struct.
@@mrbaeman39lolman60 yeah but what happens in memory ?
@@hugo-garcia In memory each pointer is just an address, so the address of the struct. The pointer would be the address of the first element of the struct (because a struct is essentially its members lined up one after the other in memory (if you ignore padding), so to access the members, the compiler only needs to jump the needed amount of bytes forward to get the address of the other struct members)
@@hugo-garcia A struct is created with a given size depending on what it contains. For example, a struct containing 2 4-bytes integers would be 8 bytes long.
Hence this struct would take several addresses in memory, two if we're using a 64-bits (or 4-bytes) OS.
When you dereference that struct, you get a pointer to the first address in memory that the struct is stored at.
The same thing happens with arrays in C. For example int array[16] declares 16 contiguous addresses in memory, and yields a pointer to the first address of that array. That's how you iterate over an array in C, you start at the first address, then access to the second element with an offset of 1 byte to the first address, etc
@@hugo-garcia Essentially, it takes that struct's age variable and sets its value to the age argument passed.
One remark. 3:50: Not next to the type, just nest to variable name:
If you write int* a, b; you'll get pointer a to integer and integer b.
Beside that pretty good material
im gonna cry
One of my computing professors, who was quite eccentric, used to like to explain pointers using a quotation from Alice Through the Looking Glass:
"You are sad," the Knight said in an anxious tone: "let me sing you a song to comfort you."
"Is it very long?" Alice asked, for she had heard a good deal of poetry that day.
"It's long," said the Knight, "but very, very beautiful. Everybody that hears me sing it-either it brings the tears into their eyes, or else-"
"Or else what?" said Alice, for the Knight had made a sudden pause.
"Or else it doesn't, you know. The name of the song is called 'Haddocks' Eyes'."
"Oh, that's the name of the song, is it?" Alice said, trying to feel interested.
"No, you don't understand," the Knight said, looking a little vexed.
"That's what the name is called. The name really is 'The Aged Aged Man'."
"Then I ought to have said 'That's what the song is called'?" Alice corrected herself.
"No, you oughtn't: that's quite another thing! The song is called 'Ways And Means': but that's only what it's called, you know!"
"Well, what is the song, then?" said Alice, who was by this time completely bewildered.
"I was coming to that," the Knight said. "The song really is 'A-sitting On A Gate': and the tune's my own invention."
en.wikipedia.org/wiki/Haddocks%27_Eyes#:~:text=The%20name%20of%20the%20song,what%20the%20name%20is%20called.
malloc failed bruh
Every video about pointers I have seen so far has given an explanation of pointers which is exactly the definition of variables.
yeah pretty much. It's just an address variable