Thread: confusion in variable-length arguments

  1. #1
    Registered User
    Join Date
    Dec 2004
    Posts
    64

    Question Understanding va_start(ap, v) in STDARG.H

    Code:
    #define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
    #define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )
    What type is of v? Not a pointer, I think, otherwise, there is no need to get the address using &v, v itself will suffice.
    Last edited by thinhare; 09-23-2005 at 08:04 AM.

  2. #2
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    When you do sizeof(fmt), all you are doing is obtaining the size of the pointer. You can't count the number/size of the arguments, that's why you need some other means. In printf, for example, you use format specifiers.

  3. #3
    Registered User
    Join Date
    Dec 2004
    Posts
    64
    yes, I agree with you. but the code in STDARG.H seems to be against what we think.
    Code:
    void minprintf(char *fmt, ...)
    // Here we can see fmt is a pointer
    Code:
    va_start(ap, fmt);
    // And the pointer being passed on to MACRO in STDARG.H
    Code:
    #define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )
    // fmt is a pointer, hence v is a pointer
    Code:
    #define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
    // v is a pointer, hence n is a pointer
    WHY here it counts the size of a pointer???

  4. #4
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    Firstly, looking at stdarg.h doesn't matter, it's upto the implementation. Even if there is a way to determine the amount of arguments on your implementation (and there likely isn't), it's not part of the C standard, so you can't rely on it for portable C programs.

    Looking at the code you pasted, what is happening here:

    Code:
    #define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )
    Is that ap is being initialised to the address of v (your pointer, fmt) plus the size of the pointer, so that it initialises ap to point to the first variable argument on the stack. Looking at INTSIZEOF(n): ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

    The &~(sizeof(int)-1) trick is to round to the nearest int, because a stack entry will also be int padded. Example, if sizeof int is 4, 4-1 is 3, ~3 is 11111100, so an & effectively zero's the two least significant bits, and because it already adds sizeof(int)-1, this will always be a round up. Example, if sizeof fmt is 6, it will round to 8, if sizeof fmt is 4, it will round to 4, if sizeof fmt is 8, it will round to 8 (assuming 4 byte ints). The reason this is done is that the last fixed parameter can be any type, not necessarily a char *

    So, it is merely calculating where the first variable argument is located, it doesn't work out how many there are.

    Hope I've explained clearly enough.
    Last edited by cwr; 09-23-2005 at 12:27 AM.

  5. #5
    Registered User
    Join Date
    Dec 2004
    Posts
    64
    Quote Originally Posted by cwr
    Example, if sizeof fmt is 6, it will round to 8, if sizeof fmt is 4, it will round to 4, if sizeof fmt is 8, it will round to 8 (assuming 4 byte ints). The reason this is done is that the last fixed parameter can be any type, not necessarily a char *
    Maybe I didn't make myself clear. You said "if sizeof fmt is 6", OK, there must be a way to count it so we can know about it. And what I doubt is the implementation in the STDARG.H in whihc it count the size by _sizeof_ a char pointer, which, as we know, will always get 4, the size of storage of a pointer. Say we passed some argument to miniprintf like this:
    Code:
    miniprintf("%c = %d\n", c, c);
    Here fmt is a pointer to the address that stores the string "%c = %d\n". Obviously the size of which is not 4. But in the implement, sizeof(fmt) will only get 4.DO YOU NOT THINK SO?
    Last edited by thinhare; 09-23-2005 at 05:09 AM.

  6. #6
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    An array or a string literal is passed to a function as a pointer to the first element. For example, with "%c = %d\n", the address of the first element (%) is passed. Therefore, sizeof(fmt) yielding 4 is correct as this is the size of the passed pointer. Incidentally, this is why you can change an array passed to a function and this change is seen in the calling function. No copy of the array is made.

  7. #7
    Registered User
    Join Date
    Dec 2004
    Posts
    64
    Quote Originally Posted by cwr
    Code:
    #define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )
    Is that ap is being initialised to the address of v (your pointer, fmt) plus the size of the pointer ...
    I don't think so. Because the size of the pointer here will be 4, unchanged. And that we expect, that needs to be plused, is the length of the string the pointer is pointing at, but not pointer itself.

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    char array[100], *pointer = array;
    
    printf("array = %i\npointer = %i\n", sizeof(array), sizeof(pointer));
    
    /*
    prints (on a 32-bit computer):
    
    array = 100
    pointer = 4
    */
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. variable arguments in functions
    By Stonehambey in forum C++ Programming
    Replies: 11
    Last Post: 02-22-2008, 05:10 AM
  2. Replies: 10
    Last Post: 09-27-2005, 12:49 PM
  3. variable length records for strings
    By teja22 in forum C Programming
    Replies: 1
    Last Post: 02-08-2002, 07:49 PM
  4. Need help
    By awkeller in forum C Programming
    Replies: 2
    Last Post: 12-09-2001, 03:02 PM
  5. Variable Allocation in a simple operating system
    By awkeller in forum C Programming
    Replies: 1
    Last Post: 12-08-2001, 02:26 PM