This guy is an absolute legend. Just when i though i had mastered pointers, the concept manages to leave me bamboozled again. Thank you for your amazing work! ❤
This video is a must-watch for any C programmer. The concept of arrays vs pointers, the decaying of arrays into pointers and how everything is handled in memory is crucial in understanding C.
This is the first channel I look at when there is something I don't understand about the subject.I can find everything I'm looking for, even what I'm not looking for 😄. Thank you for such valuable information. 😊
Me too, I often try to try to look for alternative channels so my view is not too concentric. But I always find I have to return here. Best channel for c
Thank you very much for sharing this positive feedback! :-) It means a lot to me that these videos are helpful, I’m glad to hear they are clearing up details.
passed all the morning watching videos on array dacay on other guys' "famous" channels, BUT your explainations are ALWAYS the best, precise, concise, starting from scratch and working up. GREAT WORK!
@@PortfolioCourses Like for real , If I had lecturer like you , I would not dislike C/C++ as I do now, but as you make topics clear, I am kinda getting in "like" with C ,thanks 😁
I made some tests about pointers and pointers to an entire array, and I found that if you dereference a pointer to an entire array like a int (*)[5], it will obtain a pointer int * to the first element on this array pointer. So that's why in 11:00 momment was printed an adress. To get the correct behaviour, you need to add an extra dereference operator *, and the line will be: printf(" **(matrix[1] + 1): %zu
", **(matrix[1] + 1)); So the dereference order stays: int (*)[5] -> int * -> int Which is similar to: int ** -> int * -> int But the int ** and int (*)[5] types aren't interchangeable Curiosity: The names of a N-Dimensional matrix decay to pointers to an entire first (N-1)-Dimentional Array of the N-Dimensional Array, excluding the n = 1 case. Then we have: int array1[5]; //1D int array2[5][5]; //2D int array3[5][5][5]; //3D Therefore: array1 decays to a int * to the first element. This case is exclusive to the rule. array2 decays to a int (*)[5] to the first row of the matrix, and a row is a 1D array. array3 decays to a int(*)[5][5] to the first 2D matrix of the 3D matrix. Another Curiosity: If you use the reference operator & in a matrix instead of either a matrix row or in a vector, you will obtain a pointer to an entire matrix, and the type stays something like int (*)[3][5], and the order of the dereference stays: int (*)[3][5] -> int(*)[5] -> int * -> int And the detail is that these operations, all of them, returns the first element, row or matrix of the array referenced. Then if I have a 3D multidimensional like this: int matrix[5][5][5]; &matrix -> pointer to the entire 3D matrix &matrix[0] -> pointer to the FIRST 2D matrix in the 3D matrix &matrix[0][0] -> pointer to the FIRST ROW in the FIRST 2D matrix in the 3D matrix &matrix[0][0][0] -> pointer to the FIRST ELEMENT in the FIRST ROW in FIRST 2D matrix in the 3D matrix.
Yeah, I did play around, too. But because of the line where he type-casted to int*. In my opinion it would be more correct just to add square brackets to actually get the int* out of it: (&matrix[1] + 1)[0]; Although I kinda expected to get actual int value out of it, but instead it gives a pointer. But again, reinterpreting address through type-cast in this case is not correct even though it works. Adding index operator eliminates all the casts. But sure in this explanatory video it gives deeper understanding about the addresses and "everything is an int unless you tell that it's something else". By the way, he got a warning, but it still compiled. In c++ you get straight compilation error. Can't do that without a cast or extra dereference as you did or as I did.
With just this one video, you throw a clear examole of an" ideal teacher with a great depth of knowledge about every single concept".Sir,PLEASE PLEASE MAKE a Playlist for DSA as it is absolutely crucial and difficult. A teacher like you ought to teach such critical concepts,kindly understand. Thank you soooo much for the videos and hope you do a dsa course for us needy.
Your explanation is the best explanation I've ever seen. I grasped so many things from your videos and I am still watching them; thanks a million Dr Kevin.
It is a great relief to watch this video made by someone who truly understands the concepts! (This video was recommended to me after two greatly confused videos on this topic by "Code with Huw" managed to frustrate me to no end. He starts out with the intention to address the misconception that an array in C is a pointer, and ends up arguing that an array in C is an address....lol?)
A key thing people miss is that array types DO actually exist (and hence array variables also exist), and that arrays decay to a pointer to the first element when (essentially) they are used as an RVALUE. Ie, when used in an expression. Notably, 'sizeof' is a compiler operator that doesn't take an rvalue; likewise '&' takes an lvalue (not an rvalue) so it also doesn't cause decay. Pointer arithmetic, the '*' function, and passing as a parameter to a function all DO take an rvalue and so all auto decay!
Of course the C language doesn't help with the array/pointer relationship by having two (at least) weirdly inconsistent syntax cases... presumably added because they were handy. (1) int a[5]; // An array of 5 int int a[5] = {11, 22, 33, 44, 55}; // An array of 5 int int a[] = {11, 22, 33, 44, 55}; // An array of 5 int *BUT* int a[]; // Is NOT an array! It is syntactic sugar for: int *a; (2) f("abc"); // "abc" is a 'char *' to the first element of a literal character array. char *p = "abc"; // "abc" is a 'char *' to the first element of a literal character array. *BUT* char a[] = "abc"; // is syntactic sugar for: char a[] = {a', 'b', 'c', '\0'};
@@corwin-7365 I think "int a[];" only declares a pointer variable when used in a (pre-ansi, given the semicolon) function declaration? If I am wrong, then I agree that C should not allow this. Edit: it seems C indeed does not allow this (outside of function declarations). Regarding (2), I would say in all cases "abc" is an array of char of length 4, i.e. {'a', 'b', 'c', 0}. Such an array sometimes/often decays to a pointer to the first element. It is interesting that it sometimes decays and sometimes does not when used in an initialiser statement. But I guess int *a = { 1, 2, 3, 4, 5 }; also works? Edit: funny, it does not. Edit2: Stackoverflow, "why can you initialize a string pointer as a string literal, but not as an array?", answers that { ... } In C is not an array but just a list of values, and can indeed also be used to initialise structs. "abc" on the other hand defines an array. edit3: apparently you can make it work: int *a = (int []){ 1, 2, 3, 4, 5 }; By prefixing (int []) you create a compound literal of that type (since C99). I've learned something new...
I think this videos is showing the differences between arrays and pointers in C quite well. It also gets real quirky when you add memory areas you got with malloc and treated like an array to the mix
You're welcome, and thank you very much for the kind words... the traffic on the channel has grown a lot of the last year, hopefully it keeps growing. :-)
Very interesting explanation. I studied C very long years ago, your videos are great refresh to details many programmers don't pay attention to. Thank you Kevin.
Bravo dude! You have a gift for teaching so clearly. I was just looking at the main function second parameter this morning, how you can write char *argv[] or char **argv, and I couldn't get it...but watching this made it click. Thank you!
You’re welcome Fabiano! I’m glad to hear you enjoyed it, if there are ever any topics your interested in seeing covered feel free to share them, and I can add them to my “video idea list”. :-)
@@PortfolioCourses Hi... no... C programming. Being more specific, a Linux network event driven architecture, like demonstrated in "GH eileen-code4fun NginxEventLoop". I really want to understand this topic, but I know it's super advanced. Thanks.
@@fusca14tube Oh OK I understand now. I am hoping to do some more basic networking in the future, this one is more advanced for sure, but I've added to my list of future ideas. 🙂
Thanks Dr kevin, well explained as usual , the term 2D array makes it more complex to understand I like to break it like this : matrix[3][5] is an array of 3 elements of type int[5], now I can see how can I declare a pointer of type int[5] (or pointing to an element of type int[5]) that will point of the first element of matrix, int (*pointer_matrix)[5] = matrix ; same as ----- > int (*pointer_matrix)[5] = &matrix[0] ; if I do something like this : int(*pointer_matrix)[5] = matrix[0] ; it will be wrong because matrix[0] will be decayed into a pointer of type (int*) instead of (int(*)[5] ) it gets more complex with functions 🙃🙃.
Nice video! One humble request, re 8:07: I'd love it if you'd use the term parentheses here, and save the word brackets for specifically the [] characters. I know it sometimes also gets used to just talk about the idea of bracketing something in something else, and thus can apply to (), {}, [], and even ... I just find that it nice to call those parentheses (or "round brackets"), braces ("curly brackets"), brackets ("square brackets'), and chevrons ("angle brackets"), and keep things specific. Again, you're not wrong, just a humble request.
You know that's really interesting, I just went down the rabbit hole of reading about all the different kinds of brackets and all the different names for them. :-) In the school system that I grew up in it was common to call all of those brackets, and then to make distinctions when necessary like square brackets, round brackets, "squiggly brackets", etc. I'll think about that for future videos though.... I usually try to use whatever language is more common, but I have exceptions... I pronounce "char" in a way that's not incorrect ("car"), but it's rare. It's hard to break 20-30 year habits haha...
@@PortfolioCourses haha, yeah… I think I say char like car sometimes, and like care other times, and I haven’t put enough introspection into figuring put when or why I choose one or the other, I just know I use both. :) As for what’s common, I imagine maybe there are regional variations or something?? Like, I don’t think I ever heard anyone using brackets in a generic way until a few years ago… but now I’ve heard it a number of times. So… I don’t know what changed, but… yeah. Thank you for taking it as a gentle request for the future, as intended. And certainly if you forget, no big deal. :)
@@PortfolioCourses yeah… well, I don’t remember ever hearing it in Silicon Valley in the 1990’s and early 2000’s, but then when I went back there circa 2015, I was starting to. So… 🤷🏻♀️
Pointer arithmetic was Ritchie's biggest mistake. In general C keeps things simple as it should . But in the case of pointer arithmetic it's trying to be too "helpful" so that you don't have to be explicit as a coder. That just makes it confusing: if "+1" just meant "add one" all this confusion would go away. KISS, Dennis. KISS!
In general when looking at older tech/languages/etc like C, I find it incredible how decisions made by one person or even a handful of individuals last on and have ramifications decades later.
@@PortfolioCourses With this piece of code below, I got a SEGFAULT. I thought the problem was " char *str = string1; ". So I changed it to " char *str = (char *) &string1; " and now everything works just fine. But I don't really really know why is that. In my head, if I passed the adress of the first char of string literal it would iterate just fine... I know that I have to pass the adress of the entire chunck ... Can you explain this one? Thanks for considering my request! int main(){ const char *string1 = "18e22cd2188f"; const char *string2 = "18E22CD2188F";
char *str = string1; while (*str) { *str = toupper((unsigned char) *str); str++; } printf(" "); for(int k = 0; string2[k]; k++){ printf("%c" , string2[k]); } return 0; } PS: Sorry if I made any grammar mistakes. English is not my first language.
@@matheuslbatista I think you have the right idea.. string1 would give you the address of the first char, and that is what you want to assign to str. The issue is that string1 is a const char pointer but str is a char pointer. So I think that's why a typecast to (char *) made it work. 🙂
Thank you making this video! Everything regarding arrays/pointers makes way more sense now. However, I am trying to replicate what you have discussed on one of my Ubuntu VMs using VSCode. I am running into a format error in which my compiler is saying that %zu expects an argument of type size_t. I know I can just use %p to see the hex, however, I would like to see the decimal notation as you have shown in the video. Any recommendations/suggestions? Thanks!
If u modified that statement to : "int *pointer[5] = &matrix[1] + 1;" ? u will get a scary red message instead of a cute orange warning. from my little knowledge I think u are trying to initialize an array of pointers pointing to an int with a pointer pointing to an array of 5 integers I'm not sure about my explanation above but I'm sure that u cannot initialize an array with another array directly using the = operator , u can initialize the elements of the array 1 by 1 using a loop or use memcpy to do it at once.
With things like this it's great to give it a try and see! :-) If we make that change pointer would become an array of 5 int pointers and we will get an error.
sorry my first reply was not related to the video, all u have to do is adding parentheses around the variable (pointer) and the asterisk like this : int (*pointer)[5] = &matrix[1] + 1; // now the variable (pointer) is a pointer pointing to an object of type int[5]
I would expect matrix[1] to point to the second row and matrix[1][0] to point to the first element of the second row of matrix. Why does matrix[1] decay to matrix[1][0] ? Doesn't seem logical since clearly the second element in matrix is a row, not a value inside that row.
My compiler - gcc on Ubuntu - says I should use %ls instead of %zu, but then when I use it it just does not print the address. Very odd, nio idea what is going on. I do can make it work with %ld but also get the same warning as with &zu.
why when we do sizeof(array) it returns the (byte of int )*number of elements if it is the pointer of the first element why it did not return just 4 byte all of the time
When we have an array like: int array[10], then if we are using 'array' like an array and not like a pointer, then 'array' is not a pointer to the first element. It's really an array of 10 ints, and so sizeof(array) will give us the size of that array. BUT if we ARE using an array like a pointer, say we have "*(array + 1)" and do some pointer arithmetic to get the 2nd element of the array, then what happens is that the array "decays to a pointer". And "array" in this case decays to to a "pointer to the fist element". So arrays like this become ("decay to") a pointer to the first element when we treat them like pointers. :-)
Great video, but one thing is confusing to me. I know that array and &array don't refer to the same thing, but why does array == &array??? Correct me if I'm wrong but, array == &array is saying that the value of array is equal to its location in memory.
It's because the memory addresses are the same. array decays to a pointer to the first element of the array... i.e. the memory address of the first array element. &array gives us the pointer to the entire array, which is also going to be the memory address of the first element. So they compare equally because they have the same value, even though one is technically a pointer to the first element and one is technically a pointer to the entire array. Hopefully this helps! :-)
@@PortfolioCourses I think my confusion lies in the phrase "decays to a pointer". To my knowledge, the array will decay to a pointer when it's passed to a function. The function's stack frame will hold the array(address of first element) as a value in its respective parameter. But on its own the array is simply memory address, no?
Essentially yes, "array" is just a memory address, the memory address of the first element. But the way things behave sometimes depends on the context in which they are used. array[4] will give us the memory address of the 5th element in the array, for example.
Please sir, do you have some examples about : pointer to an array VS pointer to a pointer, when and how to use this particular pointer if we want to find for example the size of the array ... I 'm confused and wanted to clarify this point please... (why sometime we write **ar and not *ar[] espacially when the size of the array is dynamically allocated. I thing this is why in the main function we have main(int argc, char *argv[]) Thanks !
I don't have any examples of this yet, but this is a good idea for a future video so I will add this to my list. :-) Though that said, I'm not sure if we *can* get the size of an array when have *ar[], I believe that's why we need argc in the case of the main function.
@@PortfolioCourses Thanks for your response Yep for a new video 🙃!!💪!!! ... I just saw your example "th-cam.com/video/4_2BEgOFd0E/w-d-xo.html" // Dynamically Allocate Memory For An Array Of Strings // very interesting too!
No, arr and &arr are not the same, that's what's covered in this video. :-) If you have questions about what's in the video I can try to help explain, but the video discusses why arr and &arr are not the same.
@@PortfolioCourses ya i saw it but like in below code #include int main(){ int arr[10]={1,2,3,4,5}; int *ptr=arr; *ptr++; printf("%d",*ptr); return 0; } It is printing 2 only i thought it will add 5×4=20 to the ptr.
I think that's a precedence thing, the operators have different precedence: www.tutorialspoint.com/cprogramming/c_operators_precedence.htm. So if you have: *ptr++; The ++ will work first, incrementing the pointer ptr to point to the next int. So instead of pointing to 1 it points to 2. The dereference * operator than happens afterwords, but it has no effect because it's just the value "2" but nothing is being done with it. Then on the next line when printf() is called, ptr has been set to point to '2' now so that is what is output. Hopefully this helps! :-)
I'll be watching this multiple times.. I'm having such trouble with an spi function taking a const uint16_t *in.. Ptrs themselves aren't bad, but arrays for some reason still woosh over my head.
thanks for this Video :) in order to make peace with douple pointer 😅 can you just please make a video about douple Pointer and espicially descripe how to use douple pointer in oeder to creat an array of Strings!! :)
Hmm maybe one day I can make a video on "double pointers" that's a good idea thanks! 🙂I do have this video on dynamically allocating an array of strings: th-cam.com/video/4_2BEgOFd0E/w-d-xo.html.
The pointer concept is not difficult. What makes it difficult to recognize what is what is the C syntax when it comes to pointers which is awful. Pointers are easy, the syntax is confusing.
I agree the syntax makes pointers more challenging than they need to be. 🙂 Lots of people have left comments on videos over the years saying the same thing too!
Yes it is called the address operator, but it's not incorrect to refer to it as the & ("and") operator either. We do this all the time when talking about different operators, referring to the symbol used when talking about the operator.
@@PortfolioCourses I disagree. The AND operator is a bitwise and logical operator. The name of an operator refers to the function it performs, not the name of the symbol used. Using incorrect names for operators just makes things confusing for people learning C
@@baz078-n2i Learning that people call things different names is an important part of learning to program. 🙂 We call base classes in object oriented programming parent classes, super classes, etc, it's just part of being a programmer that there isn't always one "correct" way to say things. I try to stay consistent within my own videos, that's what a good resource should do, because ultimately there's going to be different words for the same thing. For example prominent C programming resources also call the & operator the "reference operator" too, which is probably coming from C++, or from * being referred to as the de-reference operator, but there's not much we can do about it. Bitwise and is one & and logical and is two &&s, those are two different operators technically. The important thing is to understand what it does, focusing on the terminology isn't important unless it's inaccurate, unclear or inconsistent, none of which apply to the way I'm using the word "and operator" in this video.
The all this sh*t is not because of a flexibility of C, but because of lack of definitivity. Pointer should be an address, and increasing of an antes should always increase an address by a byte, regardless the size of array element. Because pointer is an address, no metter what data it point at. So I assume it as a problem in C. Who is no accept it and has different vision - let’s discuss.
This guy is an absolute legend. Just when i though i had mastered pointers, the concept manages to leave me bamboozled again. Thank you for your amazing work! ❤
This video is a must-watch for any C programmer. The concept of arrays vs pointers, the decaying of arrays into pointers and how everything is handled in memory is crucial in understanding C.
I’m glad you enjoyed it! :-)
This is the first channel I look at when there is something I don't understand about the subject.I can find everything I'm looking for, even what I'm not looking for 😄. Thank you for such valuable information. 😊
Thank you so much for this positive feedback, hearing things like this is so encouraging to me and I really appreciate it. :-)
Me too, I often try to try to look for alternative channels so my view is not too concentric. But I always find I have to return here. Best channel for c
Every small detail about c is crystal clear here in this channel..Keep it up bro...
Thank you very much for sharing this positive feedback! :-) It means a lot to me that these videos are helpful, I’m glad to hear they are clearing up details.
really good video. really helpful how you formatted the print statements so that everything was in line. You do the small things really well.
Thank you for the kind feedback Arman, I really appreciate that! 😀
passed all the morning watching videos on array dacay on other guys' "famous" channels, BUT your explainations are ALWAYS the best, precise, concise, starting from scratch and working up. GREAT WORK!
Mr. all of your videos are 100% understandable unlike lecturers at my university. well done !
Thank you very much for the positive feedback, I'm really glad to hear you're finding the videos understandable. 🙂
@@PortfolioCourses Like for real , If I had lecturer like you , I would not dislike C/C++ as I do now, but as you make topics clear, I am kinda getting in "like" with C ,thanks 😁
@@duldulatori3123 Hahaha aww thanks again for the kind feedback, and you're welcome! 🙂
Your programming language tutorials are one of best on YT, amazing job!
For C language, this has to be the go to channel. Period!
Thanks a ton! Sir!
One day, not today, but one day I will learn how to speak as cohesive, clear and straight-to-the-point as this gentleman.
I made some tests about pointers and pointers to an entire array, and I found that if you dereference a pointer to an entire array like a int (*)[5], it will obtain a pointer int * to the first element on this array pointer. So that's why in 11:00 momment was printed an adress. To get the correct behaviour, you need to add an extra dereference operator *, and the line will be:
printf(" **(matrix[1] + 1): %zu
", **(matrix[1] + 1));
So the dereference order stays:
int (*)[5] -> int * -> int
Which is similar to:
int ** -> int * -> int
But the int ** and int (*)[5] types aren't interchangeable
Curiosity:
The names of a N-Dimensional matrix decay to pointers to an entire first (N-1)-Dimentional Array of the N-Dimensional Array, excluding the n = 1 case.
Then we have:
int array1[5]; //1D
int array2[5][5]; //2D
int array3[5][5][5]; //3D
Therefore:
array1 decays to a int * to the first element. This case is exclusive to the rule.
array2 decays to a int (*)[5] to the first row of the matrix, and a row is a 1D array.
array3 decays to a int(*)[5][5] to the first 2D matrix of the 3D matrix.
Another Curiosity:
If you use the reference operator & in a matrix instead of either a matrix row or in a vector, you will obtain a pointer to an entire matrix, and the type stays something like int (*)[3][5], and the order of the dereference stays:
int (*)[3][5] -> int(*)[5] -> int * -> int
And the detail is that these operations, all of them, returns the first element, row or matrix of the array referenced. Then if I have a 3D multidimensional like this:
int matrix[5][5][5];
&matrix -> pointer to the entire 3D matrix
&matrix[0] -> pointer to the FIRST 2D matrix in the 3D matrix
&matrix[0][0] -> pointer to the FIRST ROW in the FIRST 2D matrix in the 3D matrix
&matrix[0][0][0] -> pointer to the FIRST ELEMENT in the FIRST ROW in FIRST 2D matrix in the 3D matrix.
Yeah, I did play around, too. But because of the line where he type-casted to int*. In my opinion it would be more correct just to add square brackets to actually get the int* out of it: (&matrix[1] + 1)[0]; Although I kinda expected to get actual int value out of it, but instead it gives a pointer. But again, reinterpreting address through type-cast in this case is not correct even though it works. Adding index operator eliminates all the casts. But sure in this explanatory video it gives deeper understanding about the addresses and "everything is an int unless you tell that it's something else".
By the way, he got a warning, but it still compiled. In c++ you get straight compilation error. Can't do that without a cast or extra dereference as you did or as I did.
With just this one video, you throw a clear examole of an" ideal teacher with a great depth of knowledge about every single concept".Sir,PLEASE PLEASE MAKE a Playlist for DSA as it is absolutely crucial and difficult.
A teacher like you ought to teach such critical concepts,kindly understand. Thank you soooo much for the videos and hope you do a dsa course for us needy.
Your explanation is the best explanation I've ever seen. I grasped so many things from your videos and I am still watching them; thanks a million Dr Kevin.
Thank you very much Mohammed! :-)
Been a minute since I’ve worked with memory/C, this was immensely helpful and probably saved countless hours. Thanks!
You’re welcome, I’m so glad to hear this was helpful for you! :-)
It is a great relief to watch this video made by someone who truly understands the concepts!
(This video was recommended to me after two greatly confused videos on this topic by "Code with Huw" managed to frustrate me to no end. He starts out with the intention to address the misconception that an array in C is a pointer, and ends up arguing that an array in C is an address....lol?)
Indeed! Huw sadly did a disappointing job, adding confusion rather than clarity.
A key thing people miss is that array types DO actually exist (and hence array variables also exist), and that arrays decay to a pointer to the first element when (essentially) they are used as an RVALUE. Ie, when used in an expression. Notably, 'sizeof' is a compiler operator that doesn't take an rvalue; likewise '&' takes an lvalue (not an rvalue) so it also doesn't cause decay. Pointer arithmetic, the '*' function, and passing as a parameter to a function all DO take an rvalue and so all auto decay!
Of course the C language doesn't help with the array/pointer relationship by having two (at least) weirdly inconsistent syntax cases... presumably added because they were handy.
(1)
int a[5]; // An array of 5 int
int a[5] = {11, 22, 33, 44, 55}; // An array of 5 int
int a[] = {11, 22, 33, 44, 55}; // An array of 5 int
*BUT*
int a[]; // Is NOT an array! It is syntactic sugar for: int *a;
(2)
f("abc"); // "abc" is a 'char *' to the first element of a literal character array.
char *p = "abc"; // "abc" is a 'char *' to the first element of a literal character array.
*BUT*
char a[] = "abc"; // is syntactic sugar for: char a[] = {a', 'b', 'c', '\0'};
@@corwin-7365 I think "int a[];" only declares a pointer variable when used in a (pre-ansi, given the semicolon) function declaration? If I am wrong, then I agree that C should not allow this.
Edit: it seems C indeed does not allow this (outside of function declarations).
Regarding (2), I would say in all cases "abc" is an array of char of length 4, i.e. {'a', 'b', 'c', 0}. Such an array sometimes/often decays to a pointer to the first element. It is interesting that it sometimes decays and sometimes does not when used in an initialiser statement. But I guess
int *a = { 1, 2, 3, 4, 5 };
also works?
Edit: funny, it does not.
Edit2: Stackoverflow, "why can you initialize a string pointer as a string literal, but not as an array?", answers that { ... } In C is not an array but just a list of values, and can indeed also be used to initialise structs. "abc" on the other hand defines an array.
edit3: apparently you can make it work:
int *a = (int []){ 1, 2, 3, 4, 5 };
By prefixing (int []) you create a compound literal of that type (since C99). I've learned something new...
@@corwin-7365 Exactly! Array types exist, so that should be the end of the discussion, right?
I've spent days trying to find a resolution to my confusion, in differentiating 'array' and '&array'. This video was extremely helpful, subbed.
That's excellent to hear this video was able to help you out, and welcome aboard! :-)
I think this videos is showing the differences between arrays and pointers in C quite well.
It also gets real quirky when you add memory areas you got with malloc and treated like an array to the mix
These videos deserve a lot more views. They are really good. Thanks.
You're welcome, and thank you very much for the kind words... the traffic on the channel has grown a lot of the last year, hopefully it keeps growing. :-)
Very interesting explanation. I studied C very long years ago, your videos are great refresh to details many programmers don't pay attention to. Thank you Kevin.
You're welcome Firas! :-)
I love your videos going full c and your videos help me so much to understand these tricky concepts. Thanks again 🙏
simply brilliant, these questions are asked in interviews to check proficiency of the candidate in pointers
Thank you for the positive feedback Satvik, I hope this video is able to help people with those interview questions! :-)
Bravo dude! You have a gift for teaching so clearly. I was just looking at the main function second parameter this morning, how you can write char *argv[] or char **argv, and I couldn't get it...but watching this made it click.
Thank you!
You're very welcome, I'm glad the video helped make it click! :-D
the pointer arithmetic side of arrays are so cool, and your video just made it better!
I agree it is cool, and I’m glad you enjoyed the video! :-)
AWESOME!!!! Please, keep doing this kind of videos! Thank you!!!
You’re welcome Fabiano! I’m glad to hear you enjoyed it, if there are ever any topics your interested in seeing covered feel free to share them, and I can add them to my “video idea list”. :-)
@@PortfolioCourses Can you explain advanced topics related to Linux network?
@@fusca14tube When you say linux network, do you mean the terminal (shell) commands?
@@PortfolioCourses Hi... no... C programming. Being more specific, a Linux network event driven architecture, like demonstrated in "GH eileen-code4fun NginxEventLoop".
I really want to understand this topic, but I know it's super advanced. Thanks.
@@fusca14tube Oh OK I understand now. I am hoping to do some more basic networking in the future, this one is more advanced for sure, but I've added to my list of future ideas. 🙂
Thank you very much for this thorough explanation, you provided an invaluable insight, and I'm very grateful for it
You’re very welcome! :-)
I’m glad I found your course and videos. But wonder I nearly failed C lo those many decades ago.
I’m glad you found them too! One of the better programmers I know failed introductory programming 3 times.
Thank you for sharing knowledges and source code!
All videos are great! But this one solved one of the problem I struggle to understand always :) Thanks.
That's awesome, glad to hear that Selim, and you're welcome! 😀
This guy is a legend greeting from England ❤
Thank you, greetings from Canada! :-)
terrific instructor
I'm glad you're enjoying the teaching! :-)
Thanks Dr kevin, well explained as usual , the term 2D array makes it more complex to understand I like to break it like this : matrix[3][5] is an array of 3 elements of type int[5], now I can see how can I declare a pointer of type int[5] (or pointing to an element of type int[5]) that will point of the first element of matrix,
int (*pointer_matrix)[5] = matrix ; same as ----- > int (*pointer_matrix)[5] = &matrix[0] ;
if I do something like this : int(*pointer_matrix)[5] = matrix[0] ; it will be wrong because matrix[0] will be decayed into a pointer of type (int*) instead of (int(*)[5] )
it gets more complex with functions 🙃🙃.
Thanks for sharing!
your videos are clear and with good examples. thank you sir
You're welcome Robel! :-) I'm glad that you find the examples are good and the videos clear.
Nice video!
One humble request, re 8:07: I'd love it if you'd use the term parentheses here, and save the word brackets for specifically the [] characters. I know it sometimes also gets used to just talk about the idea of bracketing something in something else, and thus can apply to (), {}, [], and even ... I just find that it nice to call those parentheses (or "round brackets"), braces ("curly brackets"), brackets ("square brackets'), and chevrons ("angle brackets"), and keep things specific. Again, you're not wrong, just a humble request.
You know that's really interesting, I just went down the rabbit hole of reading about all the different kinds of brackets and all the different names for them. :-) In the school system that I grew up in it was common to call all of those brackets, and then to make distinctions when necessary like square brackets, round brackets, "squiggly brackets", etc. I'll think about that for future videos though.... I usually try to use whatever language is more common, but I have exceptions... I pronounce "char" in a way that's not incorrect ("car"), but it's rare. It's hard to break 20-30 year habits haha...
@@PortfolioCourses haha, yeah… I think I say char like car sometimes, and like care other times, and I haven’t put enough introspection into figuring put when or why I choose one or the other, I just know I use both. :)
As for what’s common, I imagine maybe there are regional variations or something?? Like, I don’t think I ever heard anyone using brackets in a generic way until a few years ago… but now I’ve heard it a number of times. So… I don’t know what changed, but… yeah.
Thank you for taking it as a gentle request for the future, as intended. And certainly if you forget, no big deal. :)
Yes I suspect it's regional, in Canada brackets is "mostly" used but parentheses is also used.
@@PortfolioCourses yeah… well, I don’t remember ever hearing it in Silicon Valley in the 1990’s and early 2000’s, but then when I went back there circa 2015, I was starting to. So… 🤷🏻♀️
Wow, such a great explanation 🎉
I’m glad you enjoyed it Sravana! :-)
i mean this is what i was exactly looking for , thank u so much ❤
You’re very welcome! :-)
good and useful points. nice clean method of presenting essential topics.
I'm glad you enjoyed it Dimitrios! :-)
very good explanation thanks for your helpful videos
amazing, thank you very much for this fantastic video.
Excellent video, thank you so much!
This video is priceless man thank you so much i was thinking about kms lmao
Pointer arithmetic was Ritchie's biggest mistake. In general C keeps things simple as it should . But in the case of pointer arithmetic it's trying to be too "helpful" so that you don't have to be explicit as a coder. That just makes it confusing: if "+1" just meant "add one" all this confusion would go away. KISS, Dennis. KISS!
In general when looking at older tech/languages/etc like C, I find it incredible how decisions made by one person or even a handful of individuals last on and have ramifications decades later.
There are very few concepts you need to understand to master pointers.
Most important is understanding 'type of pointer'.
Great video! Thanks!
You’re welcome Matheus, I’m glad you enjoyed it! :-)
@@PortfolioCourses
With this piece of code below, I got a SEGFAULT. I thought the problem was " char *str = string1; ". So I changed it to " char *str = (char *) &string1; " and now everything works just fine. But I don't really really know why is that. In my head, if I passed the adress of the first char of string literal it would iterate just fine... I know that I have to pass the adress of the entire chunck ... Can you explain this one? Thanks for considering my request!
int main(){
const char *string1 = "18e22cd2188f";
const char *string2 = "18E22CD2188F";
char *str = string1;
while (*str) {
*str = toupper((unsigned char) *str);
str++;
}
printf("
");
for(int k = 0; string2[k]; k++){
printf("%c" , string2[k]);
}
return 0;
}
PS: Sorry if I made any grammar mistakes. English is not my first language.
@@matheuslbatista I think you have the right idea.. string1 would give you the address of the first char, and that is what you want to assign to str. The issue is that string1 is a const char pointer but str is a char pointer. So I think that's why a typecast to (char *) made it work. 🙂
Nice!👍👍👍
Thank you making this video! Everything regarding arrays/pointers makes way more sense now. However, I am trying to replicate what you have discussed on one of my Ubuntu VMs using VSCode. I am running into a format error in which my compiler is saying that %zu expects an argument of type size_t. I know I can just use %p to see the hex, however, I would like to see the decimal notation as you have shown in the video. Any recommendations/suggestions? Thanks!
So that's pretty much useful to calculate the size of the array.
13:22 what if the statement modified as
"int *pointer[5] = &matrix[1] + 1;" ? & the warning will go away or not?
If u modified that statement to :
"int *pointer[5] = &matrix[1] + 1;" ?
u will get a scary red message instead of a cute orange warning.
from my little knowledge I think u are trying to initialize an array of pointers pointing to an int with a pointer pointing to an array of 5 integers
I'm not sure about my explanation above but I'm sure that u cannot initialize an array with another array directly using the = operator , u can initialize the elements of the array 1 by 1 using a loop or use memcpy to do it at once.
With things like this it's great to give it a try and see! :-) If we make that change pointer would become an array of 5 int pointers and we will get an error.
sorry my first reply was not related to the video, all u have to do is adding parentheses around the variable (pointer) and the asterisk like this :
int (*pointer)[5] = &matrix[1] + 1; // now the variable (pointer) is a pointer pointing to an object of type int[5]
Thanks for sharing that! :-)
best of luck keep going
Thank you! 🙂
It is perhaps worth mentioning that sizeof is a function where this decay of array pointers don’t happen.
sizeof() is not a function, it’s an operator: th-cam.com/video/2wNc15926X4/w-d-xo.html
@@PortfolioCourses Thanks for pointing out this video!
I would expect matrix[1] to point to the second row and matrix[1][0] to point to the first element of the second row of matrix.
Why does matrix[1] decay to matrix[1][0] ? Doesn't seem logical since clearly the second element in matrix is a row, not a value inside that row.
You are a god teacher man I love you
Thank you for the love Maor! :-)
My compiler - gcc on Ubuntu - says I should use %ls instead of %zu, but then when I use it it just does not print the address. Very odd, nio idea what is going on. I do can make it work with %ld but also get the same warning as with &zu.
Love it 😍
I'm glad to hear you love it! :-D
why when we do sizeof(array) it returns the (byte of int )*number of elements if it is the pointer of the first element why
it did not return just 4 byte all of the time
When we have an array like: int array[10], then if we are using 'array' like an array and not like a pointer, then 'array' is not a pointer to the first element. It's really an array of 10 ints, and so sizeof(array) will give us the size of that array. BUT if we ARE using an array like a pointer, say we have "*(array + 1)" and do some pointer arithmetic to get the 2nd element of the array, then what happens is that the array "decays to a pointer". And "array" in this case decays to to a "pointer to the fist element". So arrays like this become ("decay to") a pointer to the first element when we treat them like pointers. :-)
Wow will I ever need to use it?
Great video, but one thing is confusing to me.
I know that array and &array don't refer to the same thing, but why does array == &array???
Correct me if I'm wrong but, array == &array is saying that the value of array is equal to its location in memory.
It's because the memory addresses are the same. array decays to a pointer to the first element of the array... i.e. the memory address of the first array element. &array gives us the pointer to the entire array, which is also going to be the memory address of the first element. So they compare equally because they have the same value, even though one is technically a pointer to the first element and one is technically a pointer to the entire array. Hopefully this helps! :-)
@@PortfolioCourses
I think my confusion lies in the phrase "decays to a pointer".
To my knowledge, the array will decay to a pointer when it's passed to a function. The function's stack frame will hold the array(address of first element) as a value in its respective parameter.
But on its own the array is simply memory address, no?
Essentially yes, "array" is just a memory address, the memory address of the first element. But the way things behave sometimes depends on the context in which they are used. array[4] will give us the memory address of the 5th element in the array, for example.
THANK YOU SIR!
You're welcome! 😀
Hey man quick question what IDE do you use I see a lot of youtubers use it.
In this video I’m using Xcode on a Mac. :-)
Please sir, do you have some examples about : pointer to an array VS pointer to a pointer, when and how to use this particular pointer if we want to find for example the size of the array ... I 'm confused and wanted to clarify this point please...
(why sometime we write **ar and not *ar[] espacially when the size of the array is dynamically allocated. I thing this is why in the main function we have main(int argc, char *argv[])
Thanks !
I don't have any examples of this yet, but this is a good idea for a future video so I will add this to my list. :-) Though that said, I'm not sure if we *can* get the size of an array when have *ar[], I believe that's why we need argc in the case of the main function.
@@PortfolioCourses Thanks for your response Yep for a new video 🙃!!💪!!! ... I just saw your example "th-cam.com/video/4_2BEgOFd0E/w-d-xo.html" // Dynamically Allocate Memory For An Array Of Strings // very interesting too!
Sir, please make a video on function pointer as member of array of structures
One day I might do that Muneer, I dont know when though. :-)
nice pls post more finding.
Thank you! And I'm just curious, what do you mean by more finding? Like finding elements in arrays? Or more videos like this? I'm just curious. :-)
What about char *argv[]? Array of pointers to char with indefinite size.
really thank's prooooooooooo
Int arr[10];
Int *ptr;
Is ptr=arr,ptr=&arr and ptr=&arr[0] same ?
No, arr and &arr are not the same, that's what's covered in this video. :-) If you have questions about what's in the video I can try to help explain, but the video discusses why arr and &arr are not the same.
@@PortfolioCourses ya i saw it but like in below code
#include
int main(){
int arr[10]={1,2,3,4,5};
int *ptr=arr;
*ptr++;
printf("%d",*ptr);
return 0;
}
It is printing 2 only i thought it will add 5×4=20 to the ptr.
I think that's a precedence thing, the operators have different precedence: www.tutorialspoint.com/cprogramming/c_operators_precedence.htm. So if you have:
*ptr++;
The ++ will work first, incrementing the pointer ptr to point to the next int. So instead of pointing to 1 it points to 2. The dereference * operator than happens afterwords, but it has no effect because it's just the value "2" but nothing is being done with it.
Then on the next line when printf() is called, ptr has been set to point to '2' now so that is what is output. Hopefully this helps! :-)
I'll be watching this multiple times.. I'm having such trouble with an spi function taking a const uint16_t *in..
Ptrs themselves aren't bad, but arrays for some reason still woosh over my head.
ti (the instrunt into the channel rack) and then it crashes the soft soft... Can soone help please?
I'm not sure what you're asking, maybe someone else can help.
My gcc compiler warns me against the use of %zu (expects a size_t type)
thanks for this Video :) in order to make peace with douple pointer 😅 can you just please make a video about douple Pointer and espicially descripe how to use douple pointer in oeder to creat an array of Strings!! :)
Hmm maybe one day I can make a video on "double pointers" that's a good idea thanks! 🙂I do have this video on dynamically allocating an array of strings: th-cam.com/video/4_2BEgOFd0E/w-d-xo.html.
@@PortfolioCourses thank you very much 🙈😇
@@muhisaleh4598 You're welcome! 🙂
Let’s go!!!
Haha I love the enthusiasm! :-)
Great
Thank you Prakhar! :-)
The pointer concept is not difficult. What makes it difficult to recognize what is what is the C syntax when it comes to pointers which is awful. Pointers are easy, the syntax is confusing.
I agree the syntax makes pointers more challenging than they need to be. 🙂 Lots of people have left comments on videos over the years saying the same thing too!
we need the difference b/n p[] and *p
Word
Thank you! :-)
It's called an address operator, not an and operator
Yes it is called the address operator, but it's not incorrect to refer to it as the & ("and") operator either. We do this all the time when talking about different operators, referring to the symbol used when talking about the operator.
@@PortfolioCourses I disagree. The AND operator is a bitwise and logical operator. The name of an operator refers to the function it performs, not the name of the symbol used. Using incorrect names for operators just makes things confusing for people learning C
@@baz078-n2i Learning that people call things different names is an important part of learning to program. 🙂 We call base classes in object oriented programming parent classes, super classes, etc, it's just part of being a programmer that there isn't always one "correct" way to say things. I try to stay consistent within my own videos, that's what a good resource should do, because ultimately there's going to be different words for the same thing. For example prominent C programming resources also call the & operator the "reference operator" too, which is probably coming from C++, or from * being referred to as the de-reference operator, but there's not much we can do about it. Bitwise and is one & and logical and is two &&s, those are two different operators technically. The important thing is to understand what it does, focusing on the terminology isn't important unless it's inaccurate, unclear or inconsistent, none of which apply to the way I'm using the word "and operator" in this video.
The all this sh*t is not because of a flexibility of C, but because of lack of definitivity. Pointer should be an address, and increasing of an antes should always increase an address by a byte, regardless the size of array element. Because pointer is an address, no metter what data it point at. So I assume it as a problem in C. Who is no accept it and has different vision - let’s discuss.
I like C but this stuff was such a mistake
I get a lot of comments like this on my videos, so I suspect your thoughts are widely shared. :-)
@@PortfolioCourses Well even if C had some big mistakes your videos help a lot, thank you!
You're welcome, I'm glad the videos are helpful! :-)
I'm too later for tNice tutorials, I'll be back stoned...
OK sounds good, but I feel like this should be a joint decision!
AWESOME!!!! Please, keep doing this kind of videos! Thank you!!!
Thank you! 😀