Thread: How to Determine size of array (non-char) from its Pointer?

  1. #1
    Devil™
    Join Date
    Oct 2007
    Location
    IIT-Kharagpur, India
    Posts
    104

    Question How to Determine size of array (non-char) from its Pointer?

    How to determine the size of the array which is passed as a parameter to the function?

    How to check the termination element?
    for char strings it is '\0'

    I dont want some global var, templates to have arraylen varible..
    I just want to extract just as we do for char strings

  2. #2
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    You can't then. You have to store something somewhere. For char strings, you have to have the extra '\0' char. You can do the same kind of thing for other array types, but, again, you have to store something somewhere.

  3. #3
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    The standard practise is to pass the size along with the array, like this:
    Code:
    void Func( char* buf, int sizeof_buf )

  4. #4
    Devil™
    Join Date
    Oct 2007
    Location
    IIT-Kharagpur, India
    Posts
    104
    but the system knows that what all are the mem locations that come under the array..
    and why cant we (program)?

    anyway.. whats the best way to realize this? (passing an array around functions and modules)
    I dont like the concept of using globals for arrays parameters..
    I am afraid that in a long code it might get tampered..

    but if we pass it from the function arguments.. how to pass them for some functions where they just take some function pointer and not params?
    ex: signal(SIGXXX, myfunction)

  5. #5
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    I don't know what you mean by saying the system knows about how big the array is. Some systems allow you to retrieve that information from a pointer to the first element of an array and some systems don't.

    Do what was previously suggested. Have your function accept a pointer and a size of the array.

    As for your last question, I have no idea what the question is. Function pointers have nothing to do with arrays. If you mean how to have the function accept a void * that points to an array's first element, then you could pass a pointer to a struct that contains the array and the size. Otherwise, you can mimick the C string solution and keep an extra element of the array set at 0.

  6. #6
    Devil™
    Join Date
    Oct 2007
    Location
    IIT-Kharagpur, India
    Posts
    104
    from the first thing, I meat that system generates segfault. so it knows the mem loc boundaries.

    and as the last thing..
    according to the example cited above..
    consider the pseudo code here
    Code:
    #define MY_CONST 20
    void my_handler(int signal_number) //I cant change this function params :(
    {
       /*I want to sort my_array here without using globals */
    }
    
    int main()
    {
        int my_array[MY_CONST];
        signal(SIGXXX,my_handler);
       /*I populate my_array here & send signal from some other process*/;
        exit(0);
    }
    I am trying to make a signal handler..
    I cant make it take my own sort of parameters..
    how to pass the array pointer & its size now?

  7. #7
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    You can't do that without using global or static variables.

  8. #8
    Devil™
    Join Date
    Oct 2007
    Location
    IIT-Kharagpur, India
    Posts
    104
    well.. fine then..
    thanks for your help

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Actually, it is possible to determine the size of an array. Though it isn't documented and I can't gaurantee it works.
    Call _msize with your pointer. It returns the size of the memory block allocated (on the heap only and only with new/delete, aka malloc and co). Divide by sizeof(*pointer), and you should have the number elements.
    Heap functions say they can return more memory than requested, so I'm not sure if this is a gauranteed solution.
    This was, of course, tested under C++ with memory allocated with new.

  10. #10
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    It's not a portable function. As I said before, some systems... compilers and O/S specific calls, allow you to retrieve information like this, but some do not. I would not recommend people sacrifice portability for something like this.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    When calling malloc, it actually stores information before and after your memory block (or at least after your memory block, at least in debug mode) and it also stores a header with information about the block, including the block size! Which can then be retrieved by _msize.
    If malloc isn't portable, then this doesn't work, of course...

  12. #12
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    If all of your assumptions are based upon Visual Studios, then you will no doubt have incorrect beliefs about portability.

    What I meant, which I thought was clear, was that _msize() is not portable. I doubt anyone would think that I'm saying malloc() is not portable. If you want me to take you seriously, I suggest you reciprocate.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    From what I understand, all _msize does is look up the size in the header. So _msize depends on malloc, but if what you are saying, it does not. It is platform specific or something?
    Meh. Anyway, it works on Windows, but on other platforms it might not, so beware.

  14. #14
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Quote Originally Posted by Elysia View Post
    It is platform specific or something?
    Yes, that's what I meant by non-portable.

    It's not available in any of the headers, to my knowledge, of the version of MinGW I currently have now. With that said, MinGW appears to be able to link properly with the function anyway.

    Still, it's not something I would recommend. Passing the buffer size along with a bufffer, or array size with an array, appears to be one of the better solutions.

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Also, it wouldn't work if you do something like this:
    Code:
    int *a = malloc(1000);
    
    int *b = &a[100]; 
    
    size_t x = _msize(b);
    And a comment
    from the first thing, I meat that system generates segfault. so it knows the mem loc boundaries.
    Yes, the system will generate segfaults when you access INVALID memory addresses. That isn't to say that this is IMMEDIATELY at the end of the current block of memory. Memory blocks for the purposes of memory protection and thus related to segfaults [in common architectures] are 4KB a piece, so if you allocate 16 bytes, you could write 4000+ bytes before the system faults - and it may even go much further than that, since often the memory allocator will use "slabs" or "heaps" of memory, so it asks the OS for, say 1MB, to have as a "spare memory". It then splits this into smaller portions as needed - and only when you run off the end of the 1MB will it FAIL [and that may well be after you've overwitten a bunch of other data]. Segfaults are really the "last resort" when it comes to runtime protection.

    It is true that malloc() [and friends] store the size of the memory allocated somewhere - it may be immediately before your memory block, it may be somewhere else. The trouble is that there's no guarantee that this will be readable in some useful way - it may not even be stored in a "clear" way, and it may not be exactly the amount of memory allocated - e.g. if you allocate 100 bytes [25 integers], the malloc-function may decide to round that up to the nearest even 16, 32, 64 or 128 bytes. To store two lenghts, one of the "actual used length" and one of "the asked for length". There is no reason for the run-time functions to store both of those numbers, storing just 128 would be fine - but that would mean that any function digging out that stored size would be returning 128, not 100.

    As a side note: The reason the allocation is done in "bigger blocks than what you asked for" is twofold:
    1. There is data stored in the header that is preferrable if it's aligned to some machine boundary so that the processor will read it fast - in some architectures, it will even fault if you get it wrong. x86 is flexible and allows "any" boundary to hold any type of data, but it's slower to read data that is "unaligned". This probably only "forces" alignment of 4 or 8 byte boundaries.
    2. Caches are important in modern processors. Making sure that the data you store is aligned on a cache-line boundary helps achieve better overall performance. Most memory allocations are at least a cache-line in size anyways, so it's not usually a large "loss".

    --
    Mats

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Fixing my program
    By Mcwaffle in forum C Programming
    Replies: 5
    Last Post: 11-05-2008, 03:55 AM
  2. Heapsort
    By xENGINEERx in forum C Programming
    Replies: 2
    Last Post: 03-30-2008, 07:17 PM
  3. typedef for pointer to array of char
    By curlious in forum C++ Programming
    Replies: 1
    Last Post: 12-13-2003, 04:21 PM
  4. comparing fields in a text file
    By darfader in forum C Programming
    Replies: 9
    Last Post: 08-22-2003, 08:21 AM
  5. How do you search & sort an array?
    By sketchit in forum C Programming
    Replies: 30
    Last Post: 11-03-2001, 05:26 PM