1 00:00:05,470 --> 00:00:08,639 So at this point, you may be wondering how we can allocate an entire array 2 00:00:08,639 --> 00:00:11,849 of integers and store its address into a pointer to an integer. 3 00:00:12,469 --> 00:00:14,610 That's a good question, and it's critical that you understand 4 00:00:14,610 --> 00:00:17,479 the relationship between arrays and pointers in c++. 5 00:00:19,499 --> 00:00:23,230 Remember that the value of an array name is the location or the address 6 00:00:23,240 --> 00:00:27,159 of the first element of the array, and the value of a pointer is an address. 7 00:00:27,780 --> 00:00:30,780 So if a pointer points to the same type of data, as the array 8 00:00:30,780 --> 00:00:34,340 elements, then the pointer and the array name are the same 9 00:00:34,340 --> 00:00:36,139 as far as c++ is concerned. 10 00:00:36,840 --> 00:00:39,760 The only difference is that the array name is not a variable, 11 00:00:39,770 --> 00:00:40,680 so you can't change it. 12 00:00:40,740 --> 00:00:44,320 But otherwise, all the calculations done to access array elements 13 00:00:44,370 --> 00:00:46,830 can be done with the array name or the pointer name. 14 00:00:49,710 --> 00:00:52,569 In this example, we have scores as an array of three integers. 15 00:00:53,400 --> 00:00:57,210 If you display scores, then the value of the array name is the address 16 00:00:57,210 --> 00:00:58,660 of the first element of the array. 17 00:00:59,040 --> 00:01:00,660 What if I dereference scores? 18 00:01:01,190 --> 00:01:03,839 Wait a minute scores is an array, how can I dereference that? 19 00:01:04,580 --> 00:01:07,840 Sure, scores is the address of the first array element. 20 00:01:07,840 --> 00:01:10,670 So if i go to that address, which is what dereferencing 21 00:01:10,680 --> 00:01:12,229 is, I get the integer. 22 00:01:12,500 --> 00:01:15,570 So the output statement for dereferencing scores displays 23 00:01:15,850 --> 00:01:17,240 100, the first array element. 24 00:01:17,920 --> 00:01:22,169 Now if I declare score pointer as a pointer to an integer and I initialize 25 00:01:22,179 --> 00:01:26,880 it to scores, notice that the value of score pointer is the same as scores. 26 00:01:27,570 --> 00:01:30,520 So when I dereference score pointer, we get the same results, 27 00:01:30,720 --> 00:01:34,390 the value of the element at that location which is 100, in this case. 28 00:01:35,110 --> 00:01:36,690 I know this can be a bit confusing. 29 00:01:36,910 --> 00:01:39,809 And when we head over to the IDE, I'll draw it out visually so you 30 00:01:39,809 --> 00:01:41,220 can see exactly what's happening. 31 00:01:43,849 --> 00:01:46,929 So if we can pretty much use an array name and a pointer name 32 00:01:47,459 --> 00:01:49,789 interchangeably, that means we should be able to use array 33 00:01:49,980 --> 00:01:53,100 subscripting on a pointer, right, and that's absolutely correct. 34 00:01:53,480 --> 00:01:55,890 If score pointer points to the first element of the score's 35 00:01:56,280 --> 00:01:59,580 array as it does in this example, then when we display score 36 00:01:59,580 --> 00:02:01,789 pointer sub-0, we get a 100. 37 00:02:01,950 --> 00:02:04,086 Score pointer sub-1 is 95. 38 00:02:04,086 --> 00:02:05,859 And score pointer sub-2 is 89. 39 00:02:06,150 --> 00:02:07,260 That's weird, right. 40 00:02:07,379 --> 00:02:10,459 Well not really if you understand that c++ doesn't really have true 41 00:02:10,460 --> 00:02:14,370 arrays, and that arrays are just the address of the first element in a 42 00:02:14,370 --> 00:02:16,430 chunk of memory then this makes sense. 43 00:02:17,080 --> 00:02:20,569 So does that mean that we can add the offset to the pointer variable then we 44 00:02:20,570 --> 00:02:22,090 can make a point to any array element. 45 00:02:22,329 --> 00:02:23,719 And again, yes, it does. 46 00:02:23,730 --> 00:02:24,489 Let me show you how. 47 00:02:26,350 --> 00:02:27,970 We're using the same example here. 48 00:02:28,210 --> 00:02:31,519 Notice that when we display score pointer, we get back an address. 49 00:02:31,910 --> 00:02:35,589 If we add one to score pointer, then you can see that the value of score 50 00:02:35,590 --> 00:02:38,340 pointer has increased by 4 not by 1. 51 00:02:38,920 --> 00:02:39,490 Why? 52 00:02:39,580 --> 00:02:42,950 Because we're not adding 1 to the pointer value, we're adding the size 53 00:02:42,960 --> 00:02:44,609 of 1 integer to the pointer value. 54 00:02:45,350 --> 00:02:46,519 The pointer doesn't hold integers. 55 00:02:47,090 --> 00:02:48,239 It holds addresses of integers. 56 00:02:49,030 --> 00:02:51,889 So when we add 1, we're adding the address of the next 57 00:02:51,920 --> 00:02:53,729 integer, which is 4 bytes away. 58 00:02:54,380 --> 00:02:58,090 If we add 2, we increment score pointer by 8 which is 2 integers away. 59 00:02:58,889 --> 00:03:01,510 This is the basis of pointer arithmetic, which we'll talk 60 00:03:01,520 --> 00:03:02,540 about in the next video. 61 00:03:03,400 --> 00:03:06,290 Once we have score pointer pointing to the integer that we want, 62 00:03:06,480 --> 00:03:09,410 we can simply dereference the pointer to get to the integer. 63 00:03:09,480 --> 00:03:10,579 Let me show you how that works. 64 00:03:12,200 --> 00:03:15,570 Here's the same example except that I'm dereferencing the expression. 65 00:03:15,980 --> 00:03:18,890 Notice that how we follow the pointer and display the 66 00:03:18,890 --> 00:03:20,040 integer that we point to. 67 00:03:20,260 --> 00:03:23,049 In this case, we're moving along the array using the pointer. 68 00:03:23,140 --> 00:03:24,270 That's pretty cool. 69 00:03:24,570 --> 00:03:26,859 Let's see this all together so it makes more sense. 70 00:03:29,400 --> 00:03:32,720 This table shows the equivalence between arrays and pointers. 71 00:03:33,240 --> 00:03:36,620 Notice that we can access array elements using array subscript 72 00:03:36,720 --> 00:03:40,530 or pointer subscript notation, using either the name of the 73 00:03:40,530 --> 00:03:42,100 array or the name of the pointer. 74 00:03:43,120 --> 00:03:46,929 You can also see we can use array offset or pointer offset 75 00:03:46,929 --> 00:03:50,400 notation also, using either the array name or the pointer name. 76 00:03:50,950 --> 00:03:51,989 Take your time with this. 77 00:03:51,990 --> 00:03:54,749 I know it can be confusing, but when it clicks, you'll be able to 78 00:03:54,779 --> 00:03:57,940 easily understand more advanced memory allocation principles. 79 00:03:58,590 --> 00:03:59,730 Let's head over to the IDE. 80 00:03:59,730 --> 00:04:01,600 And we'll go over some of the examples in this video. 81 00:04:03,040 --> 00:04:04,220 Okay, so I'm in the IDE. 82 00:04:04,220 --> 00:04:08,229 I'm in the section 12 workspace in the arrays and pointers project. 83 00:04:08,469 --> 00:04:11,080 I've gone ahead and written some code that uses array subscript 84 00:04:11,119 --> 00:04:15,570 notation, pointer subscript notation, pointer offset notation and array 85 00:04:15,580 --> 00:04:18,790 offset notation just so that we can walk through this and you can 86 00:04:18,800 --> 00:04:23,520 really understand the equivalence of pointers and arrays in c++. 87 00:04:23,759 --> 00:04:24,869 So let's get started here. 88 00:04:25,090 --> 00:04:29,009 First of all, I've created a scores array of integers right here. 89 00:04:29,440 --> 00:04:32,554 And I've initialized it to 100 95 and 89. 90 00:04:32,554 --> 00:04:34,590 And that's it over here in this little box over here. 91 00:04:34,590 --> 00:04:40,740 So this is 100, this is 95 and this is 89, and it's scores. 92 00:04:41,690 --> 00:04:45,159 And let's assume that this is at location 1000. 93 00:04:46,719 --> 00:04:50,790 So what that means is that this integer 100 is at location 1000. 94 00:04:51,980 --> 00:04:56,510 This integer 95 is at location 1004, assuming that we've got 4 byte 95 00:04:56,880 --> 00:04:58,270 integers which I do on my machine. 96 00:04:58,960 --> 00:05:02,700 And this 89 is at location 1008 in memory. 97 00:05:03,799 --> 00:05:06,000 Okay, we know they're contiguous because it's an array. 98 00:05:07,000 --> 00:05:13,390 Perfect, so when we display scores here, the name of an array is the address 99 00:05:13,390 --> 00:05:14,980 of the first element in the array. 100 00:05:14,980 --> 00:05:16,469 So in this case, it's a 1000. 101 00:05:16,710 --> 00:05:18,720 So we expect this to print a 1000. 102 00:05:20,969 --> 00:05:22,939 Now obviously, when i run this on my machine, I'm going to get a 103 00:05:22,940 --> 00:05:27,229 different value, but that's okay, now I've created another variable 104 00:05:27,230 --> 00:05:29,050 right here, called score pointer. 105 00:05:29,510 --> 00:05:31,980 Okay, so I'm going to put this guy -- actually, I'm going to put 106 00:05:31,980 --> 00:05:33,880 them right here score pointer. 107 00:05:36,050 --> 00:05:39,980 And score pointer, we're assigning two score pointer scores. 108 00:05:40,470 --> 00:05:44,140 Scores is the array name, which is the address of the 109 00:05:44,140 --> 00:05:45,500 first element in the array. 110 00:05:45,780 --> 00:05:50,320 So score pointers have a 1000 in it right now, and there's my pointer. 111 00:05:50,650 --> 00:05:53,930 Okay, there's no need to put the ampersand here, ampersand 112 00:05:53,930 --> 00:05:57,729 score since score the name of the array already is an address. 113 00:05:58,500 --> 00:06:00,669 So now we print out the value of score pointer. 114 00:06:00,670 --> 00:06:02,100 Well, it's a 1000. 115 00:06:03,010 --> 00:06:07,710 So these two values will print the same because they are the same, 116 00:06:07,710 --> 00:06:11,460 the name of the array and we just stored the name of the array, which 117 00:06:11,460 --> 00:06:14,069 is the address into score pointer. 118 00:06:15,270 --> 00:06:17,509 So now let's do array subscript notation. 119 00:06:18,109 --> 00:06:19,650 This is what we've been doing all along. 120 00:06:19,670 --> 00:06:22,830 Scores is an array, so score is sub-0 now look at what 121 00:06:22,830 --> 00:06:23,990 the compiler is doing here. 122 00:06:24,280 --> 00:06:32,589 The compiler is saying scores sub-0 is really 1000, right, that's what 123 00:06:32,589 --> 00:06:36,880 scores is plus 0 integers away. 124 00:06:37,170 --> 00:06:38,450 So that's gonna be a 1000. 125 00:06:38,830 --> 00:06:41,820 So it's gonna grab whatever is at location 1000 and display 126 00:06:41,820 --> 00:06:43,360 it, which is in this case 100. 127 00:06:45,400 --> 00:06:46,409 What about scores sub-1. 128 00:06:46,409 --> 00:06:52,140 So in the case of score sub-1, it's going to have scores, 129 00:06:52,140 --> 00:06:53,400 again, which is a 1000. 130 00:06:53,670 --> 00:06:55,580 And it's going to go 1 away from that. 131 00:06:55,640 --> 00:06:58,750 And it's not going to be a 1001, it's going to be 1 integer away 132 00:06:58,750 --> 00:07:02,090 from it because it knows its scores is an array of integers. 133 00:07:02,349 --> 00:07:04,409 So in this case, it's going to be a 1004. 134 00:07:04,409 --> 00:07:06,229 So it's going to go to a 1004. 135 00:07:06,780 --> 00:07:09,909 It sees the 95 and displays that. 136 00:07:10,539 --> 00:07:13,800 Then the same thing with score sub-2 will display the 89. 137 00:07:13,940 --> 00:07:16,859 Okay, that's using array subscript notation. 138 00:07:17,160 --> 00:07:19,539 Now take a look at pointer subscript notation. 139 00:07:19,540 --> 00:07:20,640 It's exactly the same. 140 00:07:20,650 --> 00:07:25,710 The only difference is that I replaced scores with score pointer, right. 141 00:07:25,750 --> 00:07:28,660 Therefore, we've got pointer and subscript. 142 00:07:28,880 --> 00:07:31,160 So again, score 143 00:07:32,760 --> 00:07:34,980 pointer sub-0. 144 00:07:36,280 --> 00:07:37,670 What is score pointer? 145 00:07:38,179 --> 00:07:43,850 A 1000, in this case, right, it's right here plus 0 away. 146 00:07:44,299 --> 00:07:48,690 So it's going to go to location 1000 and grab what's there, 147 00:07:48,900 --> 00:07:50,120 which is going to be 100. 148 00:07:51,440 --> 00:07:54,400 Remember, when we use subscript notation, we're basically 149 00:07:54,400 --> 00:07:56,050 grabbing what's at that address. 150 00:07:56,770 --> 00:07:58,960 Same thing with score pointers sub-1. 151 00:07:58,990 --> 00:08:03,570 It's going to go to a 1000 plus 1 integer away which is a 1004. 152 00:08:04,410 --> 00:08:07,180 And there's the 95, and here's the 89. 153 00:08:08,500 --> 00:08:10,130 Okay, so hopefully, that makes sense. 154 00:08:10,130 --> 00:08:13,260 Now here we've got pointer offset notation. 155 00:08:14,130 --> 00:08:16,760 We don't have any square brackets, so we're using the offset. 156 00:08:17,120 --> 00:08:18,809 Now let's start right here. 157 00:08:19,110 --> 00:08:21,949 What happens if I dereference score pointer, follow the 158 00:08:21,950 --> 00:08:23,309 pointer to where it's pointing. 159 00:08:24,070 --> 00:08:25,280 Score pointer is a 1000. 160 00:08:25,450 --> 00:08:27,080 I'm going to dereference it, which means I'm going 161 00:08:27,080 --> 00:08:28,400 to go to that location. 162 00:08:28,400 --> 00:08:32,250 Now I'm here, and what do I do, I display 100. 163 00:08:34,679 --> 00:08:35,990 Now what about this line right here. 164 00:08:35,990 --> 00:08:37,150 Let's go over that one carefully. 165 00:08:37,169 --> 00:08:41,640 We're going to say score pointer plus 1. 166 00:08:41,719 --> 00:08:44,599 Now notice parentheses, and then we dereference. 167 00:08:44,690 --> 00:08:46,949 So what happens first, what's in the parentheses. 168 00:08:47,230 --> 00:08:48,410 What score pointer? 169 00:08:48,420 --> 00:08:50,300 1000, it hasn't changed. 170 00:08:50,800 --> 00:08:51,390 Plus 1 what? 171 00:08:52,599 --> 00:08:56,480 Plus 1 whatever score pointer is pointing to, integer in this case. 172 00:08:56,759 --> 00:09:03,070 So 1004, I'm dereferencing 1004 which means I'm going to 173 00:09:03,620 --> 00:09:05,030 1004 and getting what's there. 174 00:09:05,350 --> 00:09:06,830 That's the 95. 175 00:09:07,850 --> 00:09:10,920 Same thing here, I'm going to 1008, and getting what's 176 00:09:10,920 --> 00:09:11,990 there which is an 89. 177 00:09:12,250 --> 00:09:15,050 Okay, so there's pointer offset. 178 00:09:15,469 --> 00:09:17,590 And then the last one is array offset. 179 00:09:17,980 --> 00:09:19,650 Notice here, I'm using scores. 180 00:09:19,730 --> 00:09:21,189 Well, what is an array name. 181 00:09:21,290 --> 00:09:24,780 Well, an array name is the address of the first element in the array, right. 182 00:09:25,110 --> 00:09:29,640 So dereference scores is the same as saying score sub-0 here. 183 00:09:30,799 --> 00:09:32,829 So in this case, scores is a 1000. 184 00:09:32,829 --> 00:09:36,150 So go to a 1000 and grab what's there, display a 100. 185 00:09:36,150 --> 00:09:43,750 Okay, here we've got scores plus 1 dereferenced, right. 186 00:09:43,770 --> 00:09:47,709 What's scores? The name of the array is the value of the address 187 00:09:47,710 --> 00:09:52,369 of that first element, right, there a 1000 plus 4, right. 188 00:09:52,369 --> 00:09:53,940 And I'm dereferencing that again. 189 00:09:53,959 --> 00:09:57,310 So you can see it's exactly like what we did with pointer offset. 190 00:09:57,680 --> 00:10:00,430 So we've got 95 and 89. 191 00:10:01,080 --> 00:10:04,300 So the output from this program is going to be exactly the same, 192 00:10:04,330 --> 00:10:07,840 array subscript, pointer subscript, pointer offset and array offset. 193 00:10:08,210 --> 00:10:11,210 They're equivalent as far as c++ is concerned. 194 00:10:11,520 --> 00:10:12,810 Now, why is this important? 195 00:10:13,000 --> 00:10:16,890 This is important because when we allocate arrays dynamically 196 00:10:16,890 --> 00:10:20,079 on the heap, we can -- we have to be able to walk them right, use 197 00:10:20,080 --> 00:10:22,620 them, display them, change them, do whatever we like with them. 198 00:10:23,059 --> 00:10:24,800 Well, we have a pointer to them. 199 00:10:24,800 --> 00:10:28,270 And that's what we got back when we mute that storage. 200 00:10:28,699 --> 00:10:33,100 That pointer to that array, it's going to be a pointer, so we can use 201 00:10:33,100 --> 00:10:35,020 pointer subscript notation if we want. 202 00:10:35,230 --> 00:10:38,200 We could use pointer offset notation if we want, right. 203 00:10:38,620 --> 00:10:42,570 Either one we can use and we're able to get to that array and those array 204 00:10:42,580 --> 00:10:44,030 elements really, really easily. 205 00:10:44,540 --> 00:10:47,979 All right, so let me run this and we'll be sure that 206 00:10:47,980 --> 00:10:49,590 we get the correct values. 207 00:10:50,090 --> 00:10:52,370 And you can see here, this is the important piece. 208 00:10:52,690 --> 00:10:57,310 The value of scores is that hex address right there. 209 00:10:57,690 --> 00:11:01,260 And the value of score pointer is the same hex address. 210 00:11:02,099 --> 00:11:06,250 Makes sense, right, because we assign scores to score pointer. 211 00:11:06,590 --> 00:11:10,310 And scores is the address of that first element in that array, 100. 212 00:11:11,640 --> 00:11:13,550 Then we go through array subscript notation. 213 00:11:13,550 --> 00:11:15,626 We print out 100 95 89. 214 00:11:15,630 --> 00:11:19,199 You can see pointer subscript, pointer offset and array offset, it 215 00:11:19,200 --> 00:11:20,930 seems all exactly the same thing. 216 00:11:21,910 --> 00:11:25,510 Okay, take your time, understand this, walk through it, play around with 217 00:11:25,510 --> 00:11:27,510 it, change a few things if you like. 218 00:11:28,740 --> 00:11:29,680 It's really important. 219 00:11:29,680 --> 00:11:34,410 Once you understand the equivalence of arrays and pointers in c++, 220 00:11:34,510 --> 00:11:36,600 it really opens up the world of power.