Thread: Explorations in Structs and sorting.

  1. #31
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by jimtuv View Post
    However my personality tends to drift toward taking risks so I am inclined to try out things that I probably shouldn't. And the idea of using the stack is tempting.
    The stack has a few natural limitations you should be aware of (and will become, one way or another):

    1) You can't return a stack variable from a function, because the function's stack is eliminated when it completes -- as you note, it's return value is left around, but in the case of an array such a char string, that value is a pointer, but what it points to will be gone:
    Code:
    char * somefunc() {
           char array[32];  // stack variable
           return array;  
    }
    No good (your compiler will probably tell you that)! So in this case you must malloc:
    Code:
    char * somefunc() {
           char *array = malloc(32);  // heap variable
           return array;  
    }
    This returns a pointer into the heap, which is valid until explicitly freed().


    2) The stack has a fixed maximum size set by the operating size, and it is comparatively small. Remember, local variables in main() are part of this. So if you have an array whose size is determined at runtime (not hardcoded) never put it on the stack (this is only possible with C99 anyway and pretty limited). You could play around and see at what point your program blows up because the stack is done, but of course, by doing that you limit the program -- if you want to use it on larger data sets later, you have to recode.

    3) If the array size determined at runtime is not taken from command line arguments, you have to malloc it anyway. Syntax makes anything else impossible.


    So while Elysia's point has some truth in it, in practice it is almost never of concern. Of course, you do not malloc everything. But for your primary data structures (such as the record array), the best practice is to do so. The fact that using stack memory is "faster" than allocating is completely mitigated by the fact that it is not big, whereas you can use all your RAM with the heap. This means in cases where the stack is an option, you are dealing with such a small amount of data that to malloc it would only require microscopic amounts of time -- not anything a normal person would consider at all relevant. The stack won't scale! The heap does.
    Last edited by MK27; 06-17-2010 at 07:21 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #32
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Keep in mind that when using malloc, you introduce memory allocation bugs. You must free what you allocate. Making sure you always free the memory under all conditions can be tricky. That is another reason to avoid malloc if you can.
    But now you know the advantages vs disadvantages, so it's up to you to choose what you need.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #33
    Registered User jimtuv's Avatar
    Join Date
    May 2010
    Location
    Sylvania, Ohio
    Posts
    94
    Quote Originally Posted by Bayint Naung View Post
    Code:
    void Init_person(personal_info *client, char name[NAME_SIZE],
                     int feet, double inches, int weight, int age);
    // and 
    void Init_person(personal_info *client,char *name,int feet,double inches,int weight,int age);
    I hope you realize there's no difference.?.
    yep no difference there but that's not what you had before. This is the way you put it first.

    Quote Originally Posted by Bayint Naung View Post
    Also why not define init function.

    Code:
    void init_person(personal_info *person,char *name, Height height,int weight,int age);
    
    init_person(&client[0],"MK27",height,140,99);   // eg usage
    So I was speaking of breaking the height into feet and inches.

    Quote Originally Posted by Bayint Naung View Post
    >> What is more efficient? Deleting elements in the middle of an array or a linked list?
    It just depends.
    You can't delete an element from an array. You can only reorganize the data. So to reorganize the array so that the data at a certain element is removed could be done in a number of ways. I would tend to just initialize the data with predetermined data that is out of range and then on sorts or searches just either sort that element to the end or skip it in the search.

    The big problem would be if I wanted to add a new element at array[0]. I would have to shift all the other elements up by one to make room!. That is if they fit. In an array the size is fixed so adding elements becomes a bit dangerous if the array is close to being full.


    A linked list is a bit different first you have to find the node to delete and it's predecessor then you could change the "next" pointer in the node just before the one you want "deleted" with the pointer in the soon to be deleted node. As long as both pointers point to the same place (the node following the one to be deleted) your good! This should work it is in the middle of the list or end of the list. The problem would be if the node to delete were at the beginning removing the node isn't the problem because the following node already has the pointer pointing to the correct node. It's the Head or list pointer that would have to be fixed as it would need to point to the second node not the first.

    seems like you could do this recursively. By setting up the deletion function to return the pointer of the node. Just a thought maybe I am way off.

  4. #34
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by jimtuv View Post
    The problem would be if the node to delete were at the beginning removing the node isn't the problem because the following node already has the pointer pointing to the correct node. It's the Head or list pointer that would have to be fixed as it would need to point to the second node not the first.

    seems like you could do this recursively. By setting up the deletion function to return the pointer of the node. Just a thought maybe I am way off.
    This is where pointers get slightly complicated. I'm not sure what you mean by "do this recursively", but with the delete you have two choices and you seem to have the first one:

    1) Always return the head node in case it has changed (because the head was deleted). Here assume the node is identified using a char string, "val":
    Code:
    node *delete(node *head, char *val);  // function prototype
    /* usage */
    head = delete(head, "this one");
    2) The other option is to pass in the address of the pointer which points to head:
    Code:
    void delete(node **head, char *val);  // function prototype
    /* usage */
    delete(&head, "this one");
    This is called a "pointer to a pointer" and that's another important concept . It allows you to reassign head without using the return value -- so the return value could be reserved for something else, say an error code. Beyond that it's just a matter of style, but you should know how to do both for cases when you cannot use the return value in this way.

    Quote Originally Posted by Elysia View Post
    Keep in mind that when using malloc, you introduce memory allocation bugs.
    Memory bugs are usually of this form:
    Code:
    char *ptr;
    while (some loop) {
          ptr = malloc(123);
          [do something with pointer]
    }
    Since ptr was not freed or assigned to anything else in the loop, the memory to which it pointed (different memory for each iteration!) is still reserved for the duration of the program, but you now have no handle (pointer) to that memory, meaning you cannnot access or use it, or free it. This is called a memory leak.

    So in general "memory bugs" are pretty simple and easy to prevent. The only thing which makes them more potentially troublesome than something which causes a crash or bad output is that you can fail to notice them. However, use of a simple memory profiler such as valgrind (on linux) can solve that problem.
    Last edited by MK27; 06-17-2010 at 08:19 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #35
    Registered User jimtuv's Avatar
    Join Date
    May 2010
    Location
    Sylvania, Ohio
    Posts
    94
    Wow you were fast. I was just about to edit this out. LOL

    Quote Originally Posted by jimtuv View Post
    seems like you could do this recursively. By setting up the deletion function to return the pointer of the node. Just a thought maybe I am way off.
    Just thinking how someone would set up the function for deleting a node. If it should be done recursively or iteratively.

  6. #36
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Well the depth of the recursion would be the number of links you have to follow to get to the deleted node. You would run out of stack space on any moderate to large size list.

  7. #37
    Registered User jimtuv's Avatar
    Join Date
    May 2010
    Location
    Sylvania, Ohio
    Posts
    94
    Quote Originally Posted by jimtuv View Post
    You can't delete an element from an array. You can only reorganize the data. So to reorganize the array so that the data at a certain element is removed could be done in a number of ways. I would tend to just initialize the data with predetermined data that is out of range and then on sorts or searches just either sort that element to the end or skip it in the search.

    The big problem would be if I wanted to add a new element at array[0]. I would have to shift all the other elements up by one to make room!. That is if they fit. In an array the size is fixed so adding elements becomes a bit dangerous if the array is close to being full.
    This is another area I have rethought. It would be better to shift the data down over the "deleted" element rather then just putting in values out of range. So you would copy the next element on to the deleted element and continue the loop until the last one is reached

    Code:
    for ( i = loc; i < size ; i++){     // where loc is the number of the element to remove
    	array[i] = array[i+1];
    }

  8. #38
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    That'd work. You see how this will get very expensive on a big array. Which is why if you need to do deletions, a linked list is usually a better choice. They are a pretty basic and essential data structure, once you understand them it is not hard to whip an implementation up in a few dozen lines.

    C generally forces you to "hand-roll" any kind of data structure beyond an array (such as a linked list, which most other modern languages have a built in "list" type). There's an obvious disadvantage to this low level focus (it's work) -- the advantage would be that such things are almost always, by nature, more efficient than using generisized equivalents (like built-ins), esp. in terms of memory usage.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #39
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I'm curious. Give a reason why a hand-rolled out linked list would generally be more efficient in terms of memory than a generic built-in structure?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #40
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Fewer pointers, less indirection, is an educated guess, but in any case "the proof is in the pudding" -- you don't think the afforementioned mem use issue WRT to the STL is for no reason at all, do you?

    I'm not saying that makes built-ins for dummies, since they do save a lot of time, and certainly I make a lot of use of that kind of thing in a number of languages on a daily basis. But when push comes to shove, if (eg) std::map uses 40% more memory than a customized hash table or tree, then the amount of data that can be handled given some upper limit (eg, 2Gb) is 40% greater for the custom structure.

    In any case, you have tweak control of a hand-rolled structure, which pretty much by definition means there is more opportunity for optimization.
    Last edited by MK27; 06-17-2010 at 12:13 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  11. #41
    Registered User jimtuv's Avatar
    Join Date
    May 2010
    Location
    Sylvania, Ohio
    Posts
    94
    Quote Originally Posted by Elysia View Post
    Keep in mind that when using malloc, you introduce memory allocation bugs. You must free what you allocate. Making sure you always free the memory under all conditions can be tricky. That is another reason to avoid malloc if you can.
    But now you know the advantages vs disadvantages, so it's up to you to choose what you need.
    Wouldn't this be true of most any function I were to use?? I mean when I was studying user input and learning to use fgets I needed to be sure to send the correct size to it. scanf can be a disaster if you leave off the &. And any use of pointers could be a mess if you try and dereference them before they are pointing someplace useful. Bugs are introduced by bad programming practice not the proper use of the function. So avoiding any function because it may be difficult is a bit silly to me. Big caveat would be functions like gets() that seem have no safe way to use them.

    I understand what you are saying about free I am sure it can be tricky but I haven't seen much in C that doesn't have a tricky side to it. Buffer overflows, memory leaks etc are only of few of the many pitfalls.

    I think that because C doesn't hand hold the programmer makes it potentially unsafe yet also extremely fast and powerful at the same time. This is some of what makes C so interesting to me. I use the word potentially because with proper knowledge and careful application of that knowledge C should be and has proven to be very safe indeed.

  12. #42
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    What I am implying is that if you add more complexity to your program, it will cause more bugs and get harder to maintain. This holds true for anything, not just malloc/free. The advice was that you shouldn't complicate the program unnecessarily. Don't use malloc/free unless you have to. Don't use scanf unless you have to.

    Believe me, when you start making bigger programs, you will begin to see the problem. Lots of if conditions, lots of places that hold references to the same data (where should it be freed?). Excellent ways to cause memory leaks.

    Quote Originally Posted by jimtuv View Post
    I think that because C doesn't hand hold the programmer makes it potentially unsafe yet also extremely fast and powerful at the same time. This is some of what makes C so interesting to me.
    Then you should try C++, because it's even more powerful in a sense while it still holds true to its roots from C.

    I use the word potentially because with proper knowledge and careful application of that knowledge C should be and has proven to be very safe indeed.
    I don't know if C has been proven to be safe. But you are right that if used properly, then it will indeed be safe.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #43
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by Elysia View Post
    I'm curious. Give a reason why a hand-rolled out linked list would generally be more efficient in terms of memory than a generic built-in structure?
    This question serves no purpose. If I missed an important thing, let me know about it privately, but I think you refuse to deal with jimtuv on his terms and just want him to learn C through a C++ looking glass. You know that the C language doesn't even offer something built in like that. Unless you're suggesting that jimtuv go out and find a library to use. Having only that and an insistence that use of malloc and free is automatically broken to contribute only demonstrates a lack of restraint.

    I don't know if C has been proven to be safe.
    How do you prove a programming language safe? Could you make less lazy statements in the future, and say wtf you mean.

    You're being a huge troll. You're lucky I'm not a mod.

  14. #44
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by whiteflags View Post
    You're being a huge troll. You're lucky I'm not a mod.
    Nonsense. I am stating, as I have been from the beginning, that putting malloc/free into your program instead of using the stack, will cause additional bugs.
    I have nowhere said that the OP should not do it. In fact, this whole damn discussion began with the OP asking if pointers had to be used with malloc/free, and I answered, no, it doesn't have to be. It can be on the stack, if you want. It can also be malloc/free.
    I repeat:
    The OP is free to do whatever he wants, if what way he wants. I have merely stated some facts. This should not deter the OP from experimenting and learning things. This is mostly "useful information" that a programmer writing a real world application should worry about and not a student who is still learning the language.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #45
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    That's a stupid statement. That's like saying "adding scanf to your program will cause bugs". No it doesn't. You not using it right causes "bugs". Hell, I could just as well say "using arrays causes bugs", or "using the stack causes bugs" (because I can blow the stack).


    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 03-31-2009, 12:34 PM
  2. Sorting an Array of Structs not working
    By ashcan1979 in forum C++ Programming
    Replies: 9
    Last Post: 09-28-2006, 03:07 PM
  3. sorting containers of structs
    By bigSteve in forum C++ Programming
    Replies: 2
    Last Post: 01-06-2004, 02:50 PM
  4. sorting an array of structs
    By jo_jo2222 in forum C++ Programming
    Replies: 2
    Last Post: 04-08-2002, 11:52 PM
  5. sorting an array of structs
    By singletrackmind in forum C++ Programming
    Replies: 8
    Last Post: 11-13-2001, 03:33 AM