Dynamically allocated multi-dimensional arrays in C

Поделиться
HTML-код
  • Опубликовано: 20 окт 2024

Комментарии • 105

  • @MATHMATICS2012
    @MATHMATICS2012 3 года назад +18

    I have spent 3 days trying to figure this out for a school project. Your explanation was clear and to the point. Good Job! thank you!!!

  • @RuinousGrace
    @RuinousGrace 2 года назад +5

    You've demystified so many C concepts for me that I couldn't grasp through other explanations. Thank you so much!

  • @ivanlo7195
    @ivanlo7195 3 года назад +3

    I have been working on a programming assignment about operating system. Your videos help me extremely well, I was thinking like why your videos always pop up when I am searching the keyword on RUclips. You literally taught everything I need in these few days like fork() exec() wait4() dup2(), the int argc, char*argv[] and now the dynamic allocation of multi-dimensional array. Although I have take a course in c++, operating system with C language still a big barrier for me. I can't be more thankful toward your videos. Big Thank you to you

  • @ileila1682
    @ileila1682 2 года назад +2

    Thank you for your talk throughs they really helped me to understand multidimensional arrays that much more! Good job!

  • @zishiwu7757
    @zishiwu7757 4 года назад +16

    Thank you so much for this clear explanation. I always wondered why a 3 x 3 int ** matrix took up more than just 4 * 3 * 3 = 36 bytes of memory. Now I know the extra memory is for the int ** taking up 8 bytes and each row consisting of an int * taking up 8 bytes. I've been mostly using garbage collected languages like Python and Java, but I'm motivated to learn C so that I can contribute to open source projects in the future.

    • @tomaszstanislawski457
      @tomaszstanislawski457 2 года назад

      Assuming that the compiler is not smart enough to figure out something more efficient, this allocation scheme is really bad. Typically the smallest chunk allocated from malloc is 32-bytes long. Thus this code consumes 8*3=24 rounded to 32 bytes for pointers and 3*32 bytes for the data itself. It gives 128 bytes rather than optimal 36.

  • @flaviusmazilu17
    @flaviusmazilu17 2 года назад +1

    In a few minutes you saved me from hours of debugging tryina find what's wrong with it, tysm

  • @filiphedman4392
    @filiphedman4392 2 года назад +2

    Probably the best programming explanation I've ever heard and seen. You get my like and sub.

  • @chithesh2470
    @chithesh2470 2 года назад +1

    Read many articles , watched many videos but no one explained it like you did . Thank you.

  • @gregorgrattler8579
    @gregorgrattler8579 2 года назад +1

    man im trying this for about 20 hours you are my hero !!

  • @jjj23233
    @jjj23233 3 года назад +1

    So happy i discovered your channel !! thanks for the explanation and continue the good work

  • @SleepySoulMan
    @SleepySoulMan 3 года назад +2

    I love this video, and what it taught me. I was lost when it came to why my memory allocated 2D char array for a problem I was doing was not working. This man has saved me!

  • @RyeCA
    @RyeCA 2 года назад +1

    Hey, thanks so much for the video. I currently have a university class for c programming, but my lecturer didn't upload a video concerning dynamically allocated multi-dim arrays, so I had to visit youtube. Found your channel, very good explanation!

  • @pogofcz
    @pogofcz 3 года назад +3

    This tutoral is great! Thank you. I needed to (or i think it was the best option) create a 3D array and could easily apply your method.

  • @trevydandridge32910
    @trevydandridge32910 3 года назад +3

    Thank you, exactly what I needed! Liked and Subscribed.

  • @bsgamer5069
    @bsgamer5069 4 года назад +5

    Awesome video. We really need a programmer like you in youtube.

  • @stephanekeglo9394
    @stephanekeglo9394 2 года назад

    Crystal clear explanation on how to manage dynamically allocated multi-dimensional arrays in C !

  • @RajvirSangha
    @RajvirSangha 3 года назад +1

    Thank you so much! Very nicely explained. Liked and Subscribed!

  • @SMM2001
    @SMM2001 3 года назад +1

    thanks, you answered one of my important question.

  • @fountain862
    @fountain862 2 года назад

    Great illustrations with the diagrams

  • @hlokomani
    @hlokomani 2 года назад

    bruh you just demystified so much

  • @krazyolie
    @krazyolie 2 года назад

    This ties in well with why sizeof works differently for arrays.. the compiler/program is aware of the size and type, it's not in user memory. With the dynamic allocation we have to have it record it in user memory. a 1d array would be space efficient but would require more calculations to index so it's a classic memory vs performance issue.

  • @dalilam2276
    @dalilam2276 2 года назад

    thank you for the easy to follow explanation!

  • @aldotovar9231
    @aldotovar9231 3 года назад +1

    hey man! I don't really know what K&R looks like, but if it's called the C Bible, I think this would be the video version of it. NIce nice tutorials. I'll probably watch them all XD

  • @saidmilyodas6423
    @saidmilyodas6423 Год назад +1

    thank you so much .

  • @balckeagle2024
    @balckeagle2024 3 года назад +1

    THANK u i really understand with tables and draws the lessons

  • @Thelukkest
    @Thelukkest 3 года назад +1

    Perfect explanation, zero dislikes!

  • @dallamine7470
    @dallamine7470 2 года назад +1

    Sir how to get the number of rows and columns in a matrix read from a file.Thank

    • @CodeVault
      @CodeVault  2 года назад +1

      You can simply have a number that increments for every integer you read. Once you hit a new line, you know that's the number of elements in a column. For rows, you'd have to read each line in the file to find out (basically the same idea)
      You could use realloc() if you need more space in an array you've allocated dynamically

  • @jamesmorrison1308
    @jamesmorrison1308 3 года назад +1

    Well done. Thank you!

  • @soumyaaitmellouk3871
    @soumyaaitmellouk3871 Год назад

    Finally i found someone how explain this, thank you teacher

  • @kajial-mamun9191
    @kajial-mamun9191 4 года назад

    Thanks GOD , i got this video..now, my concept is very clear...Thank you sir, you deserve 1 million subscriber...please make video on data structure

  • @harveykisiangani9939
    @harveykisiangani9939 Год назад

    Thank you, it is very clear and helpful

  • @jaredamos3452
    @jaredamos3452 3 года назад +1

    Hello, when so i made the 2d dynamic array same as you but i keep getting compile warning
    "assignment to ‘int’ from ‘void *’ makes integer from pointer without a cast
    **regTable = malloc(sizeof(int*) * (numOfStudents*numOfCourses));
    ^
    "
    Im just confused why it worked in the video and not for me, i tried type casting as int and int* and still gives warning, the variable is first
    declared above main as "int **regTable;"
    any help with this would be greatly appreciated

    • @CodeVault
      @CodeVault  3 года назад +1

      **regTable is an int
      malloc returns a pointer.
      I think you meant to do *regTable = malloc(...);

  • @yourjeedost9014
    @yourjeedost9014 4 года назад +1

    Hello! I wanted to know about how to free the dynamic array which is initialized in a function that has to return that array and then I want to free that initialized array.

    • @CodeVault
      @CodeVault  4 года назад +3

      Hi! Dynamic memory initialized in a function doesn't have to be freed in the same function. You can free it anywhere you want as long as you have a pointer to it

  • @tomaszstanislawski457
    @tomaszstanislawski457 2 года назад +1

    Or simple use a pointer to an array. `int (*arr)[3] = calloc(3, sizeof *arr);` and it's done. Free with `free(arr)`. Works perfectly even if dimensions are not constants. try: `int (*arr)[m] = calloc(n, sizeof *arr);` to dynamically allocate n-by-m array

    • @nigh_anxiety
      @nigh_anxiety Год назад +1

      This also has the benefit of ensuring that all of the array memory will be contiguous as its being allocated all at once. Using a loop to allocate each element of the ** might not get contiguous memory.

  • @dimitrioskalfakis
    @dimitrioskalfakis Год назад

    very good presentation.

  • @ramiltaghiyev9712
    @ramiltaghiyev9712 Год назад

    11:55 Hi. Please explain the formula. I understand the sizeof(arr) (just numbers of 2d array) +size (arr[0]*3) (the weigh of one pointer multiplied by 3) but what is sizeof(int) 3*3 for?

    • @CodeVault
      @CodeVault  Год назад +1

      sizeof(arr) - the size of the double pointer to the pointer array. Should be 8 bytes
      sizeof(arr[0]) * 3 - the size of the pointers to the arrays. Should be 8 * 3 = 24 bytes
      sizeof(int) * 3 * 3 - the size of all integers of the whole array. Should be 4 * 3 * 3 = 36 bytes
      ^ this is the same as sizeof(arr[0][0]) * 3 * 3
      Total is 68 bytes

    • @ramiltaghiyev9712
      @ramiltaghiyev9712 Год назад

      @@CodeVault Thank you

  • @stickfigure31
    @stickfigure31 Год назад

    Would this method also be appropriate to use when you don't know how many dynamically allocated 1d arrays you need before hand or say you want to load in multiple bitmaps in memory and don't know how many or the max sized bitmap at compile time can you expand this to be a dynamically allocated 3d array? Or is there a better way to use pointers in those cases?

    • @CodeVault
      @CodeVault  11 месяцев назад

      Depending on what you need this could be a solution. Another one would be to flatten the array and calculate offsets based on the indices

  • @04.nehalsingh12
    @04.nehalsingh12 2 года назад

    awesome tutorial sir

  • @fadyhany6818
    @fadyhany6818 3 года назад +1

    i understand why you did set **arr to NULL ( because it is in the stack and when the line "free(arr)"execute the memory in the heap will get free and **arr still exist because it is in the stack which mean it is pointing somewhere ) , right?
    what i can not understand why you did set each one of arr[i] "in the for loop "to NULL each one of them is in the heap which mean once the line "free(arr)"execute. each one of them will be deleted?

    • @CodeVault
      @CodeVault  3 года назад +1

      You're completely right. It's just good practice. After freeing memory you should always set that pointer to that memory to NULL, that way it's MUCH easier to debug and fix your code. Basically, if you accidentally dereference that pointer that you just freed the memory of... there are two possibilities:
      1) Pointer is NULL so the program crashes gracefully, thus you can see where your issue is
      2) Your program accesses memory that (by chance) has access to and continues executing until it breaks elsewhere (this is much harder to track down)

  • @sandeepvy1347
    @sandeepvy1347 3 года назад +1

    Thanks bro, do more such unexplained but important topic videos.
    Btw how to allocate more size for specific sub array inside main array?
    For example I want to allocate 8 int space for a[1] and a[2] , and for rest 5 int spaces?

    • @CodeVault
      @CodeVault  3 года назад +1

      It's gonna have to be dynamically allocated. So something like this:
      int** arr = malloc(sizeof(int*) * 3);
      for (int i = 0; i < 3; i++) {
      if (i == 1 || i == 2) {
      arr[i] = malloc(sizeof(int) * 8);
      } else {
      arr[i] = malloc(sizeof(int) * 5);
      }
      }

  • @MrSportPalace
    @MrSportPalace 3 года назад

    just what I needed, thanks

  • @gahineprajval
    @gahineprajval 2 года назад

    Does architecture depends on compiler ??
    Since my laptop is based on 64bit architecture but though my result shows the value of sizeof(int**) as 4 only.

    • @CodeVault
      @CodeVault  2 года назад +2

      Yes (kinda). Your compiler can be configured to build the application for all sorts of architectures (x86, x64, ARM etc.). Modern computers can run both 32-bit and 64-bit applications. So you have your compiler configured to create a 32-bit executable and you're running that on your 64-bit machine in compatibility mode

  • @parthdeshwal4419
    @parthdeshwal4419 5 месяцев назад

    great video sir

  • @7yuui
    @7yuui 2 года назад +1

    Is it enough to only free the outer array and set it to zero without freeing each individual sub array in advance or will this cause a problem?

    • @CodeVault
      @CodeVault  2 года назад +2

      It will cause a memory leak. You basically have to have a free() call for each malloc/calloc call

    • @7yuui
      @7yuui 2 года назад +1

      @@CodeVault Thank you!

  • @culpinha
    @culpinha 2 года назад

    Thank you sir.

  • @dtv3886
    @dtv3886 3 года назад +1

    Thank you :)

  • @aviroxi
    @aviroxi 3 года назад

    thank you so much sir :)

  • @hashmath17
    @hashmath17 3 года назад

    Is it not required to typecast to int** or int* after dynamic allocation? Please reply

    • @CodeVault
      @CodeVault  3 года назад +1

      It's never required. Although it is recommended to do so in C++... in C it's not recommended

  • @pooblock4092
    @pooblock4092 3 года назад

    Great video!!!!!!! No wonder you have 0 dislikes.

  • @TankFFZ
    @TankFFZ 9 месяцев назад

    Why do you use the format specifier "%llu" instead of "%d"?
    Im new to C language!

    • @CodeVault
      @CodeVault  9 месяцев назад

      Because sizeof() returns a "unsigned long long" type (64-bit unsigned integer) instead of an "int" type (32-bit signed integer)

    • @TankFFZ
      @TankFFZ 8 месяцев назад

      @@CodeVault got it, thank you!

  • @df1322
    @df1322 3 года назад

    Thank you very much :)

  • @senpai7404
    @senpai7404 2 года назад

    can you automatically update the arrays with inputs of 4 bytes? without first storing the bytes then allocating them manually into each section of the array????

    • @CodeVault
      @CodeVault  2 года назад +1

      I'm not sure what you mean. Can you give me an example please?

    • @senpai7404
      @senpai7404 2 года назад

      @@CodeVault Basically, i'm creating a RFID scanner that stores the UIDs every time a card is detected, i want it to store up to 10 attempts and each UID consists of 4 bytes i.e. 192 313 414 21, can i have it so whenever a card gets scanned it updates the same list with every new card being detected without overwriting previous scans

    • @senpai7404
      @senpai7404 2 года назад

      if you have discord i can show you properly what i mean pls Ai#0001

    • @CodeVault
      @CodeVault  2 года назад

      You can send the code to discord.code-vault.net
      There are people there that can help you

  • @lyrichives7859
    @lyrichives7859 Год назад

    Thank you!!

  • @tylerdo2693
    @tylerdo2693 4 года назад

    I have a problem I’ve been working on. The program sums up a value with a certain number of child processes. It asks the user for number of terms and child processes to split the calculation for the number of terms. I started with making a two dimensional array. How would I loop to make just four child processes and reference the pipe for the child? Example the user puts 1000 and 4 so 1000 terms and 4 child processes.

    • @CodeVault
      @CodeVault  4 года назад +1

      I'm not sure I understand your question. You have a 2D array and you want to know how you sum each subarray (say of 250 elements in that case) in each child process? Is that right?

    • @tylerdo2693
      @tylerdo2693 4 года назад +1

      @@CodeVault Yes, so i watched your video on pipes for two way communication which helped. I run into a problem when I try to use a for loop. I create the pipe based on the user input for child processes. I need to pass from the parent the binary values of the terms, number of child processes, and say j from the for loop. Then the child does it sums and passes to the next and when they're done they pass it back to the parent to get the total. So my output would be something like Child #1 approximation for sum over 0-250 Child #2 for sum 251-500... etc and the parent would print the total. The problem i have is how do I know which child process is what. I also have a hard time figuring out how to fork() just four children.
      I wrote something like this
      int(*fd)[2];
      fd = (int(*)[])calloc(4,sizeof(fd[0]);
      for(int j = 0; j < 4; j++)
      pipe(fd[j])
      if(fork() == 0)//Child
      {
      read(fd[j])???
      }
      else
      {
      //Parent?
      }

    • @tylerdo2693
      @tylerdo2693 4 года назад +1

      Also, within my child I call a function computePartialSum()

    • @CodeVault
      @CodeVault  4 года назад +1

      To fork just 4 children you'd have to call fork() only in the parent process. Like this:
      int pids[4] = { 0 };
      for (int i = 0; i < 4; i++) {
      pids[i] = fork();
      if (pids[i] == 0) {
      break;
      }
      }
      So for every fork, each child process would hit the break statement and exit, while the parent would keep creating processes.

    • @CodeVault
      @CodeVault  4 года назад +1

      Next, to figure out which process is which you have to think about how the pids array is looking in each of the processes (suppose id1, id2, id3 and id4 are the child processes ids):
      parent pids[4] is { id1, id2, id3, id4 };
      child1 pids[4] is { 0, 0, 0, 0 }; since it never assigned any other value than 0
      child2 pids[4] is { id1, 0, 0, 0 };
      child3 pids[4] is {id1, id2, 0, 0};
      child4 pids[4] is {id1, id2, id3, 0};
      So, to figure out which process is which, you can just check the first occurence of 0 in the pids array:
      for (int i = 0; i < 4; i++) {
      if (pids[i] == 0) {
      // ... Code executed only by child i
      break; // Break so that it only executes once per process
      }
      }

  • @hitman1646
    @hitman1646 2 года назад

    GOLD
    Thanks.

  • @gourabmukherjee4848
    @gourabmukherjee4848 2 года назад

    How to get output in external window in vs code ?

    • @CodeVault
      @CodeVault  2 года назад +1

      There's an option in launch.json: code.visualstudio.com/docs/cpp/launch-json-reference#_externalconsole

  • @paladin5d781
    @paladin5d781 Год назад

    thank you so muchhh

  • @asifsaad5827
    @asifsaad5827 4 года назад

    why does all the pointer array of int type takes 64 bytes?
    although my pc id of x64 config, yet it shows 4 bytes for int type of pointer

    • @CodeVault
      @CodeVault  4 года назад +1

      Even though you are on a 64 bit machine you might be compiling your program for 32 bit. Also, make sure you dont' confuse int types with int* types. The former has 4 bytes and the latter has 8 bytes (on 64 bit).

    • @asifsaad5827
      @asifsaad5827 4 года назад

      @@CodeVault thanks!!
      🙂🙂

    • @asifsaad5827
      @asifsaad5827 4 года назад +1

      @@CodeVault noo!!
      i did take into account the fact of int* and it shows 4 bytes!!
      however,then i checked my compiler which happens to be of 32bit!!
      😅

  • @anshulyadav5217
    @anshulyadav5217 3 года назад

    wao it working fine. Nice explaination : )

  • @nawelouahrani9588
    @nawelouahrani9588 2 месяца назад

    You're the best

  • @asifsaad5827
    @asifsaad5827 4 года назад

    also, why do we need to allocate an array dynamically?
    can't do we anything else to replace the dynamically allocated array?

    • @CodeVault
      @CodeVault  4 года назад +1

      Well, there are 3 types of memory in C. Global, stack and heap. If you want the array to be allocated at all times you could allocate it globally. On the stack, it wouldn't work usually since the memory gets deallocated ones the call returns. The heap is sort of the middle ground, where you control when it gets allocated and deallocated so it's easier to optimize your memory usage.

    • @asifsaad5827
      @asifsaad5827 4 года назад

      @@CodeVault thanks a lot!!!
      but globally declared array does not require pointers which consume significant amount of memory(as we can see for heap),still when the question is about like..using a fuxed amount of memory again and again and a large amount of data,i believe heap has the upper hand there!!
      am i right??
      TIA!!
      keep up the good work,btw!

    • @CodeVault
      @CodeVault  4 года назад +2

      Yeah, when working with large amount of memory it is best to use the heap. As global memory will be saved to disk in the executable.

    • @tomaszstanislawski457
      @tomaszstanislawski457 2 года назад

      @@CodeVault Actually the proper wording should be "static", "automatic" and "dynamic", respectively. It refers to the lifetime of objects. Static are persistent, automatic are freed when the identified goes out of scope (not only when function ends) and dynamic are freed on demand. Word "global" is not technically correct because one can have static variables defined inside the function, or even a nested scope that is not accessible from outside.

  • @T-She-Go
    @T-She-Go 3 года назад

    Amazing🙌🏾

  • @Nathan-vt4zw
    @Nathan-vt4zw 2 года назад

    when we use & here ?

    • @CodeVault
      @CodeVault  2 года назад

      Whenever we want to get the address of something.
      For arrays we don't have to do this since it's redundant:
      int arr[5];
      printf("Address of array is %p", &arr);
      // is the same as
      printf("Address of array is %p", arr);
      There's this video on the topic: code-vault.net/lesson/4rx6a7yjaz:1603820088963
      and a continuation code-vault.net/lesson/wxugezii3r:1603820089003

    • @Nathan-vt4zw
      @Nathan-vt4zw 2 года назад

      @@CodeVault
      typedef struct s_list
      {
      void *content;
      struct s_list *next;
      } t_list;
      void ft_lstadd_front(t_list **lst, t_list *new)
      {
      if (!lst && !new)
      return ;
      new->next = *lst;
      *lst = new;
      }
      int main()
      {
      t_list *lst = ft_lstnew("start");
      t_list *student0 = ft_lstnew("student0");
      t_list *student1 = ft_lstnew("student1");
      ft_lstadd_front(&lst, student0);
      ft_lstadd_front(&lst, student1);
      }
      Do you have a video about using ** and & here?

  • @prateekchowdhury3337
    @prateekchowdhury3337 3 года назад

    It's not mooltaa.... It's maaaalteaaaa

  • @yomommapranked2427
    @yomommapranked2427 3 года назад

    I-
    Love you

  • @oysteijo
    @oysteijo 2 года назад

    Oh no! This is not optimal. You want to allocate all elements in one block. Then all elements are still continuous in memory. Then you can pass your 2D-array into BLAS algorithms etc. without further modifications. Also if you have many rows there will be many calls to malloc. Malloc is a system call and hence very slow. If you first allocate a array of pointers, for the beginning of each row, and then allocate the elements, you get away with two allocation no matter the dimensions of the 2D-array. Doing one allocation for each row will make you program slow.

    • @CodeVault
      @CodeVault  2 года назад

      Huh, in these videos I sometimes omit certain aspects such as performance or certain good practices that are used on production-ready projects (if they take away from the subject at hand).
      But this intriguing and I might consider making its own video. Just to fully understand: You mean to just allocate the pointers, allocate the block for all values (malloc(x * y * sizeof(int))) and then assign all the pointers to their respective addresses?

  • @mouad1995
    @mouad1995 Год назад

    love u

  • @paschalokafor9043
    @paschalokafor9043 2 года назад

    I am the 1000th person to like this video

  • @matteopisati9966
    @matteopisati9966 2 года назад

    Thank you !!!