Thread: Variable-length arg lists?

  1. #1
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223

    Variable-length arg lists?

    I have just started with Functions with variable-length argument lists, and I thought i would try using it to "optimise" one of the functions I already have. I have tryed implementing it, the compiler produces not errors/warnings, so when run the program crashes. Here is what I have currently:
    Code:
    void InsertRow(HWND hwnd, char *col1, char *col, ...)
    {
    	LV_ITEM lvItem;
    	va_list arguments;
    	int i;
    
    	lvItem.mask = 0;
    	lvItem.iItem = 0;
    	lvItem.iSubItem = 0;
    	lvItem.iItem = ListView_InsertItem (hwnd, &lvItem);
    
    	lvItem.mask = LVIF_TEXT;
    	lvItem.pszText = col1;
    	lvItem.cchTextMax = strlen (lvItem.pszText);
    	ListView_SetItem(hwnd, &lvItem);
    
            va_start (arguments, col);
    	for (i=0; col!=0; i++) {
    		lvItem.iSubItem = (i+1);
    		lvItem.pszText = va_arg ( arguments, char *);
    		ListView_SetItem(hwnd, &lvItem);
    	}
    	va_end (arguments);
    }
    I know the for loop needs fixing (its probably col!=0 [i've tried !=NULL same thing happens]) but I don't know how to fix this. Any ideas? I think (hope) this is code stright forward, if not say and I will post the old code (longer, but works).
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    printf( "%d %d", num1, num2 );
    This is an example of a vararg function which encodes the number of variable parameters in the control string. Count the number of % to determine the expected number of parameters.

    execl("prog","prog","arg","arg",(char*)NULL);
    This is an example of a vararg function which has a specific value (a NULL pointer) to mark the end of the list.

    You need to include a mechanism by which the number of arguments can be determined. There is no automatic means to do this.
    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
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Or pass an argument that contains the number of variable arguments you passed.
    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.

  4. #4
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    InsertRow uses the va_start macro to assign a pointer (arguments) to the first parameter on the stack. Next, the function uses the va_arg macro to get the values one at a time. The va_arg macro returns a value of the specified type and then increments the pointer (arguments) to point to the next item. When the pointer encounters a NULL terminator, the function uses the va_end macro to assign a value to the pointer that prevents the future use of the pointer. That is until va_start reinitializes the pointer again.

    An example follows:
    Code:
    #include <windows.h>
    #include <stdio.h>
    
    void InsertRow(HWND hwnd, char *col1, char *col, ...)
    {
        LPCTSTR pMsg;
        va_list arguments;   
        printf("%s\n", col1);
        printf("%s\n", col);
        va_start (arguments, col);  
        while ((pMsg = va_arg (arguments, LPCTSTR)) != NULL)
            printf("%s\n", pMsg);
        va_end (arguments);
    }
    
    int main(void)
    {
        InsertRow(NULL,"col1A", "Test1", "Test2", "Test3", NULL);
        InsertRow(NULL,"col1B", "Test4", NULL);
        InsertRow(NULL,"col1C", "Test5", "Test6", "Test7", "Test8", "Test9", "Test10", NULL);
        return 0;
    }

  5. #5
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223
    Thanks, I think I will go with Elysia's suggestion to pass in the number of arguments. With the function I have now, col1 is inserted fine, but the second col has been replaced with the third col. To put this another way, the forth parameter gets replaced with the fith, and so on. Here is the code:
    Code:
    void InsertRow(HWND hwnd, int argcount, char *col1, char *col, ...)
    {
    	LV_ITEM lvItem;
    	va_list arguments;
    	int i=0;
    
    	//Omitted region Same as above, works fine
    
            va_start (arguments, col);
    	for (i=0; i<=argcount; i++) {
    		lvItem.iSubItem = (i+1);
    		lvItem.pszText = va_arg ( arguments, char *);
    		ListView_SetItem(hwnd, &lvItem);
    	}
    	va_end (arguments);
    }
    //Called with the following:
    InsertRow(GetDlgItem(hwndMain, ID_LISTVIEW), 7, szProcessName,
     PIDbuf,GetProcessMemoryWSS(hProcess, buf), GetProcessMemoryPWSS(hProcess, buf),
     GetProcessPriority(hProcess), GetUserInfo(dwProcesses[i], hProcess));
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    	for (i=0; i<=argcount; i++) {
    I notice one subtle bug here. Count starts from 1 and index starts from 0. So it should be i < argcount, otherwise you're going to read 6 arguments instead of 5 when you pass 5.
    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.

  7. #7
    HelpingYouHelpUsHelpUsAll
    Join Date
    Dec 2007
    Location
    In your nightmares
    Posts
    223
    Thanks for the quick reply, but this doesn't fix the problem. whatever I change lvItem.iSubItem to it doesn't work. Changing it to i+2, leaves the second column blank, for some reason. I think va_arg ( arguments, char *); is getting the second argument instead of the first.

    ---FIXED---
    I have currently fixed the problem with an if statement, meh it works. Since what should have worked perfectly well, logically, didn't I tried the following (for loop only the ret is above):
    Code:
    for (i=0; i<argcount; i++) {
    	lvItem.iSubItem = (i+1);
    	if (i==0) lvItem.pszText = col;
    	else lvItem.pszText = va_arg ( arguments, char *);
    	ListView_SetItem(hwnd, &lvItem);
    Last edited by P4R4N01D; 02-04-2008 at 02:42 AM. Reason: Fixed
    long time no C; //seige
    You miss 100% of the people you don't C;
    Code:
    if (language != LANG_C && language != LANG_CPP)
        drown(language);

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need explanation of variable arg lists
    By Countfog in forum C Programming
    Replies: 2
    Last Post: 05-04-2008, 04:34 PM
  2. Question about printing a variable???
    By Hoser83 in forum C++ Programming
    Replies: 2
    Last Post: 03-31-2006, 01:57 PM
  3. float/double variable storage and precision
    By cjschw in forum C++ Programming
    Replies: 4
    Last Post: 07-28-2003, 06:23 PM
  4. variable length records for strings
    By teja22 in forum C Programming
    Replies: 1
    Last Post: 02-08-2002, 07:49 PM
  5. length of string etc.
    By Peachy in forum C Programming
    Replies: 5
    Last Post: 09-27-2001, 12:04 PM