Thread: Pass array pointer to function and compute size of array

  1. #1
    Registered User
    Join Date
    May 2008
    Posts
    115

    Pass array pointer to function and compute size of array

    Hi,

    why does the function return an incorrect value, here 2 instead of 5?

    Code:
    #include <stdio.h>
    
    size_t len(const short (*arr))
    {
    	return sizeof(arr)/sizeof(arr[0]);
    }
    
    int main(void)
    {
    	const short *data[5] = {14, 15, 16, 17, 18};
    	printf("%d\n", len(data));
    	
    	return 0;
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Pointers have no concept of the size of the thing they point to.
    If they did, unintentional buffer overflows would have been long banished to history.

    Code:
    void foo ( int *bar ) {
       // no idea what kind of thing bar is pointing to.
    }
    
    int main ( ) {
       int x;
       int a[100];
       int *p = malloc(10000*sizeof(*p))
       foo(&x);
       foo(a);
       foo(&a[50);
       foo(p);
    }
    > sizeof(arr)/sizeof(arr[0]);
    This does work if the array is actually in scope - it would work in main for example.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2008
    Posts
    115
    Quote Originally Posted by Salem View Post
    Pointers have no concept of the size of the thing they point to.
    If they did, unintentional buffer overflows would have been long banished to history.

    Code:
    void foo ( int *bar ) {
       // no idea what kind of thing bar is pointing to.
    }
    
    int main ( ) {
       int x;
       int a[100];
       int *p = malloc(10000*sizeof(*p))
       foo(&x);
       foo(a);
       foo(&a[50);
       foo(p);
    }
    > sizeof(arr)/sizeof(arr[0]);
    This does work if the array is actually in scope - it would work in main for example.
    OK thanks!

    So, in my example, the pointer has been passed correctly but I need to pass the size separately (if I want to do something in the function).

    Just of curiosity, what did my function actually compute?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by serge
    So, in my example, the pointer has been passed correctly but I need to pass the size separately (if I want to do something in the function).
    Yes. Alternatively, you can pass a second pointer that points to one past the end of the range that you want the function to access. Yet another possibility is that it may make sense to wrap both the pointer and the size in a struct, and in that case you can pass a pointer to the struct object.

    There is one more way that you actually have seen: designate a sentinel value, then terminate the sequence that the pointer points to with that sentinel value. This is the approach adopted for null terminated strings, where the sentinel value is the null character. However, history has shown us that this approach tends to be bug-prone in ways that can lead to security vulnerabilities, so it is not recommended.

    Quote Originally Posted by serge
    Just of curiosity, what did my function actually compute?
    The size of a pointer to short divided by the size of a short.
    Last edited by laserlight; 10-20-2019 at 03:41 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,791
    Quote Originally Posted by laserlight View Post
    However, history has shown us that this approach tends to be bug-prone in ways that can lead to security vulnerabilities, so it is not recommended.
    Citation needed :P

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Hodor View Post
    Citation needed :P
    Don't be lazy and trawl the CVE list yourself.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,791
    Quote Originally Posted by laserlight View Post
    Don't be lazy and trawl the CVE list yourself.
    There are no (yep, a total of zero) CVE entries related to sentinel values being bug-prone or a security risk; if you don't believe me, have a look.

    Knuth discusses sentinel values (and also what he calls dummy values (or dummy nodes) when discussing linked lists, searching and other related algorithms, but does not discuss them being security risks (hey, maybe it's a bug in his texts and I could get one of those cheques for $1 that he sends out)

    Edit: As bad as Wikipedia sometimes is, it usually mentions security risks. Sentinel value - Wikipedia mentions no such intrinsic bug-proneness or risk towards security and a tend to agree because I can't think of how/why a sentinel value is "bug-prone". As mentioned, sentinel values are used everywhere: for C-style strings, for linked lists, for arrays, for indicating error or not found circumstances (although depending on the source these can be called dummy values, but in essence they're sentinels). I just double-checked the CVE list and can find no bugs that have a root cause of using a sentinel.
    Last edited by Hodor; 10-20-2019 at 04:06 AM.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Hodor
    There are no (yep, a total of zero) CVE entries related to sentinel values being bug-prone or a security risk; if you don't believe me, have a look.
    Not hard to find security vulnerabilities listed related to null termination, or rather the lack thereof.

    Quote Originally Posted by Hodor
    Knuth discusses sentinel values (and also what he calls dummy values (or dummy nodes) when discussing linked lists, searching and other related algorithms, but does not discuss them being security risks (hey, maybe it's a bug in his texts and I could get one of those cheques for $1 that he sends out)
    That's because for linked lists and many other tree structures, having a sentinel value to denote past a leaf is a typical approach, though it can be possible to mitigate the issue of failing to terminate correctly with well tested libraries that abstract away this risk. The same risk mitigation could be said about null terminated strings, but not when you're writing your code own that manually uses sentinel values.

    I think that part of why this is especially a problem for arrays is also the issue of being able to access elements out of bounds without explicit errors/exceptions in the first place, but then this is an efficiency trade-off that we're obviously not going to make in C... which is also why some security folks recommend against C (and C++, even though C++ does have the security-conscious/inefficient facilities).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    May 2008
    Posts
    115
    But something still is not right, for the two print calls produce different output:

    Code:
    void myprint(const short *src, size_t len)
    {
    	int i;
    	for(i = 0; i < len; ++i) printf("%d\n", src[i]);
    }
    
    int main(void)
    {
    	const short *data[] = {14, 15, 16, 17, 18};
    	for(i = 0; i < (int)sizeof(data)/sizeof(data[0]); ++i) printf("%d\n", data[i]);
    	myprint(data, sizeof(data)/sizeof(data[0]));
    	
    	return 0;
    }

  10. #10
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,791
    Quote Originally Posted by serge View Post
    But something still is not right, for the two print calls produce different output:

    Code:
    void myprint(const short *src, size_t len)
    {
        int i;
        for(i = 0; i < len; ++i) printf("%d\n", src[i]);
    }
    
    int main(void)
    {
        const short *data[] = {14, 15, 16, 17, 18};
        for(i = 0; i < (int)sizeof(data)/sizeof(data[0]); ++i) printf("%d\n", data[i]);
        myprint(data, sizeof(data)/sizeof(data[0]));
        
        return 0;
    }
    Try
    Code:
    void myprint(const short *src, size_t len)
    {
        int i;
        for(i = 0; i < len; ++i) printf("%d\n", src[i]);
    }
     
    int main(void)
    {
        const short data[] = {14, 15, 16, 17, 18};
        int i;
        for(i = 0; i < (int)sizeof(data)/sizeof(data[0]); ++i) printf("%d\n", data[i]);
        myprint(data, sizeof(data)/sizeof(data[0]));
         
        return 0;
    }
    Not that the array should be an an array of short, not short*

  11. #11
    Registered User
    Join Date
    May 2008
    Posts
    115
    Code:
    void myprint(const short *src[], size_t len)
    fixed it.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    That's not the right fix though: now we would expect you to be working with an array of pointers to short, not an array of shorts. Look carefully at how Hodor declared the array named data in main in post #10: it is declared as an array of short. Contrast this to how you declared the array named data in main in post #9.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 01-10-2016, 01:23 AM
  2. How to pass pointer of 2d array to function
    By Alpo in forum C Programming
    Replies: 16
    Last Post: 04-25-2014, 05:21 PM
  3. Replies: 1
    Last Post: 10-21-2007, 07:44 AM
  4. pass the pointer of a two dimension array to a function
    By SoFarAway in forum C Programming
    Replies: 8
    Last Post: 04-13-2005, 05:43 AM
  5. Replies: 3
    Last Post: 04-02-2002, 01:39 PM

Tags for this Thread