Thread: dynamic array

  1. #31
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by claudiu View Post
    I SAID: What if you realize, FOR WHATEVER REASON, you don't want a long*, but a void*? The second method would imply you need to change the allocation, which is the very reason that was argued that the first option would be inferior in the first case. Hence, I provided an example where you have to change the allocation in the second method as well and argued that this is not sufficient reason to claim that the second method is superior.
    And the point we are making is that is, for all practical purposes, impossible -- such a pointer cannot be dereferenced and therefore cannot be used. (You can assign it to type_I_wanted*, but then you would naturally just change int* to type_I_wanted* instead of void*.)

  2. #32
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    The second method would imply you need to change the allocation,
    There is no situation where the size calculation changes because you are using void pointers. If you insist on using them immediately you essentially ask the compiler for sizeof(void). Using sizeof(type) to say differently isn't an example I will accept, because you have to use a defined type anyway, and therefore you can use a defined pointer type on the left of the malloc call.

  3. #33
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    Once again I must point out generic programming. A perfect example in which you allocate memory using a void pointer and cast the data to whatever you want in your user program. Yes, you can't dereference the void* but that doesn't make it useless. Why is that so hard to understand?

    Another example I can think of would be a generic slab allocator which is something very commonly used in kernels. The slab allocator uses void* to allocate whatever structs are getting used in the client programs faster than through a regular malloc call. The allocator calls a constructor for the struct via a pointer to a function provided by the user program. At that point, the memory allocated by the void* internally gets used via a cast to a specific pointer. However, this happens without the allocator's knowledge. As far as it is concerned EVERYTHING is a void pointer.

  4. #34
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Once again I must point out generic programming. A perfect example in which you allocate memory using a void pointer and cast the data to whatever you want in your user program. Yes, you can't dereference the void* but that doesn't make it useless. Why is that so hard to understand?

    Another example I can think of would be a generic slab allocator which is something very commonly used in kernels. The slab allocator uses void* to allocate whatever structs are getting used in the client programs faster than through a regular malloc call.
    Because your thinking about it the wrong way.

    With respect to generic programming, you couldn't provide me with a real world example where void * had to be used immediately. The programmer would just use regular boring pointers, even when something wants void * because void * can /point to anything/. If a variable has to be pushed on a function's stack frame as void * then the compiler can handle that without special effort from the programmer.

    If you are writing those functions, you are still using a defined type a majority of the time, whether it be char * or something fancier. A use for void * that doesn't go away or appear with an assignment does not exist.

    The slab allocator -- well I have never written one, but I speculate -- may also use void * /as a result pointer temporarily/ but that has dick to do with the allocated size.

  5. #35
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by claudiu View Post
    >"The primary practical purpose of enhancing readability or any other measure of "quality" is ensure a programmer can understand the code, in order to minimise likelihood of programmer error.
    Using readability to justify a code construct that increases likelihood of programmer error is completely at odds with that.
    Software engineering is not about writing aesthetically beautiful but bug-ridden code.
    "

    Yes and No. Another important goal of code readability is to minimize production costs. You don't want to pay a software developer to spend 90% of his time understanding old code and 10% of his time improving it, or adding new features to it. Programmer error IMO is really the programmer's concern and it is a measure of his skill.
    Yes, the purpose of code readability is to minimise costs. However, it is not just production costs that matter. It is the life cycle costs aggregated over every modification of that software. Reducing production costs is meaningless if it causes user dissatisfaction (i.e. bugs) sufficient to lose customers, or if the cost to fix those bugs significantly exceed the production costs.

    I agree with you that no programmer can expect to modify code without a sufficient understanding of it. But what are the practical circumstances in which readability matters? When the code is being modified.

    It is one thing to seek to minimise effort to understand what a section of code does. It is quite another to advocate a technique in which a well-intended programmer action can yield code that misleads some future programmer.

    It is that cascading effect that concerns me: programmer A changes a declaration, but does not realise that change generates a need for a change in another part of the code. Because that second change has not been made, programmer B is misled so, while believing she is writing correct code, actually introduces faulty code that looks correct. Subsequently this comes back as a bug report from a user. The effort for programmer C to track down and then resolve the cause can actually be quite significant, because the code continues to be misleading - and programmer C is probably trying to do that with some manager or client breathing down his neck. The immediate production costs of that may be small. The life cycle costs will be significant.

    So, essentially we have two options. The first is a code construct that reduces likelihood of misleading a development team, but potentially (I'm unconvinced, but you are) requires more programmer effort to add new functionality. The second option is one which reduces effort to understand the code, but potentially misleads the programmer into a false sense of security. You are advocating the latter.
    Quote Originally Posted by claudiu View Post
    Following this logic you could also say that all API's should be written to take into account any possible misuse. That would be a blunder of astronomic proportions. The sad truth is, no matter how bulletproof or "safe" your code is, some idiot somewhere, sometime will still be able to trip on it. This is more of an academic ideal than anything.
    Not at all. I'm arguing that code that can mislead a conscientious programmer is worse than code that a foolish programmer can trip on. The foolish programmer will get in trouble regardless. The conscientious programmer has a chance of avoiding trouble if s/he is not mislead.
    Quote Originally Posted by claudiu View Post
    >"Given that the sizes of most types are implementation defined (eg sizeof int may be 2 with one compiler/OS, and 4 or more for another) that same argument works equally well against the approach you advocate. The size of struct types are always implementation defined, due to padding (and to implementation-defined sizes of basic types).

    If you want to report the amount of raw memory being allocated, simply store n * sizeof *x in another variable, and examine that variable. That allows the value to be examined either at run time (eg print it out) or during debugging.
    "

    That's just a waste of time, when I can have it right there in front of my eyes. Yes, I may not be able to calculate how much memory I am allocating to the last byte, but given the fact that I probably know what range of machines I am coding for, I could have a pretty good idea.
    You're the one who suggested it is necessary to know the amount of memory allocated by the malloc() call. I provided a way to do that. I don't actually consider the requirement significant. If programmers need to know the exact amount of memory used by a program, they will find a way to compute it reliably.

    In any event, the fact you may know what machines you code for is only relevant if that knowledge is in the head of the programmers who eventually have to maintain your code. In the real world, management decisions often mean that some other programmer is required to (say) port your code to a new system, which was not within the range you coded for. Or, since time has past, you have forgotten the details and the documentation has been misplaced (assuming you remembered to write it).

    Quote Originally Posted by claudiu View Post
    Another argument against the use of that method of malloc-ing is that it's not as general as you may think. What if, in your long/short example before, I decided that neither would do, and I actually want variable x to be a void*?
    That's specious as, at some point, that void pointer will need to be converted into some other pointer type so it can be used.

    Yes, the "a = malloc(n * sizeof *a)" will trigger a compiler error if a is changed from a non-void pointer to a void pointer.

    The only difference is that your technique means that the malloc() call misleads some future programmer - who needs to use that allocated memory - into believing that a is a non-void pointer. The programmer then attempts to dereference that pointer, and encounters an error as a result.
    Last edited by grumpy; 04-11-2010 at 01:30 AM.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #36
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    @grumpy

    I see what you are saying. It's been a really interesting debate and I guess it all comes down to a matter of preference since both methods are correct. I appreciate the effort you put into stating your case. It was a good read.

    @whiteflags
    I'm sorry maybe I am just very tired but I don't really seem to follow your point. I don't understand what "using the void* immediately has to do with anything". This debate has been mostly about the contrary, allocating memory for a pointer FAR AWAY from its declaration. e.g. Suppose you have a global pointer declared in a different header file and allocated in another source file.

    In any case, it was a good read everyone! Best of luck in your pointer use

  7. #37
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Well that's annoying that I can't explain anything...

    I refuse to put too much more effort into this, but void * semantically does not mean anything other than "Oh here's an address to something somewhere". Therefore, I always assign void * pointers to some other type, and almost never assign /to/ void *, as it is not necessary. Even when I do assign to void * it has always been valid not to use void *. Casting them to something else is always an option, but by no means an excellent preference, when you can just assign.

    It doesn't really buy you anything if you need to find a declaration. That notion you want to convince me of is truly bizarre, since it implies trusting the closest thing you see, which may be a sizeof thing or a cast. The only thing that matters of course is

    foo bar;

    And in IDEs, bar will show up as foo in a tooltip. Such a nicety.
    Last edited by whiteflags; 04-11-2010 at 02:44 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Dynamic Array Resizing
    By dld333 in forum C++ Programming
    Replies: 13
    Last Post: 11-04-2005, 12:13 AM
  2. need help with dynamic array syntax
    By soldyne in forum C Programming
    Replies: 3
    Last Post: 10-11-2005, 01:59 PM
  3. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM
  4. 2D dynamic array problem
    By scsullivan in forum C Programming
    Replies: 3
    Last Post: 12-30-2002, 10:02 PM
  5. Dynamic array allocation and reallocation
    By purple in forum C Programming
    Replies: 13
    Last Post: 08-01-2002, 11:48 AM