i'm learning win32 from Programming Windows Fifth Edition book, but i need ask something about these code:

/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
SCRNSIZE.C −− Displays screen size in a message box
(c) Charles Petzold, 1998
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

int CDECL MessageBoxPrintf (TCHAR * szCaption, TCHAR * szFormat, ...)
{
    TCHAR szBuffer [1024] ;
    va_list pArgList ;

    // The va_start macro (defined in STDARG.H) is usually equivalent to:
    // pArgList = (char *) &szFormat + sizeof (szFormat) ;
    va_start (pArgList, szFormat) ;

    // The last argument to wvsprintf points to the arguments
    _vsntprintf (szBuffer, sizeof (szBuffer) / sizeof (TCHAR), szFormat, pArgList) ;

    // The va_end macro just zeroes out pArgList for no good reason
    va_end (pArgList) ;

    return MessageBox (NULL, szBuffer, szCaption, 0) ;
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    int cxScreen, cyScreen ;
    cxScreen = GetSystemMetrics (SM_CXSCREEN) ;
    cyScreen = GetSystemMetrics (SM_CYSCREEN) ;
    MessageBoxPrintf (TEXT ("ScrnSize"), TEXT ("The screen is %i pixels wide by %i pixels high."),cxScreen, cyScreen) ;
    return 0 ;
}
  • why using 'CDECL' in MessageBoxPrintf() function declaration? i can ignore it, but why use it?
  • the _vsntprintf(), in 2nd argument, we can use -1, right?(for the function calculate the size automatic)
  • can anyone explain to me how the MessageBoxPrintf() function works? i'm confused between the args 'loop' functions and the return value :(

Recommended Answers

All 18 Replies

_cdecl is the default calling convention for Micosoft Visual Studio. There is no need to explicitly use CDECL.

_vsntprintf() -- wrong. (link). How is _vsntprintf() supposed to know the size of the first parameter???

Please study a tutorial on variable arguments, then you will understand how that function is working. vsntprintf () is doing all the hard work of combining all the strings in the last parameters to that function.

commented: thanks +2

the exemple that you give me is diferent, because uses the for loop... but maybe it's the same.
the _vsntprintf() link isn't working: http://msdn.microsoft.com/en-us/library/1kt27hek.aspx
"_cdecl is the default calling convention for Micosoft Visual Studio. There is no need to explicitly use CDECL."
but why use it? what means?
thanks for correct me. thanks

the _vsntprintf() link isn't working

You're right -- I must have copied the wrong url into the clipboard.

but why use it? what means?

I don't use it. there may be a compiler setting to change the default to something else, but I'm not sure about that. That's the only reason I can think of to use CDECL.

commented: thanks +0

ok.... thanks
anotherthing: i'm trying understand more the arguments list:

double MessageBoxSum(double number,...)
{
    double sum;
    va_list ArgumentList;
    va_start ( ArgumentList, number );
    int x = 0;
    for ( x=0; x < sum; x++ )
    {
        // Loop until all numbers are added
        sum += va_arg ( ArgumentList, double );
    }
    va_end(ArgumentList);
    char text[1024];
    _vscprintf(text,sizeof (text) / sizeof (char),number,ArgumentList);

   return MessageBox(NULL, text,TEXT("hi"),MB_OK);
}

i get 2 errors:
- warning: passing argument 2 of '_vscprintf' makes pointer from integer without a cast [enabled by default];

  • note: expected 'va_list' but argument is of type 'unsigned int';
  • error: too many arguments to function '_vscprintf'

(these function, for learn, is just add several numbers and show the sum in MessageBox)
but what i'm doing wrong? :(
(some informations are confused and never tell us about these type of errors :( )

When you get that kind of error just look up the function and see what arguments it expects. Simple use google to do that. In the case of _vscprintf() you are passing the wrong arguments. (link)

sorry, you have right.
is these line:

_vscprintf(text,sizeof (text) / sizeof (char),"%f",sum);

but i continue with errors :(

now i change the function and works, but i always get 0 (zero) :(

double MessageBoxSum(double number,...)
{
    double sum=0;
    va_list ArgumentList;
    va_start ( ArgumentList, number );
    int x = 0;
    for ( x=0; x < sum; x++ )
    {
        // Loop until all numbers are added
        sum += va_arg ( ArgumentList, double );
    }
    va_end(ArgumentList);
    char text[1024];
    sprintf(text,"%f",sum);
    return MessageBox(NULL, text,TEXT("hi"),MB_OK);
}

MessageBox() does NOT return a double. Look it up.

true... sorry. but even so the for loop isn't correct :(
i'm testing the sum value with prinf and i continue with 0(zero)

i see i'm doing several errors.

double average ( int num, ... )
{
  va_list arguments;                     // A place to store the list of arguments
  double sum = 0;

  va_start ( arguments, num );           // Initializing arguments to store all values after num
  for ( int x = 0; x < num; x++ )        // Loop until all numbers are added
    sum += va_arg ( arguments, double ); // Adds the next value in argument list to sum.
  va_end ( arguments );                  // Cleans up the list

  return sum / num;                      // Returns the average
}

the num is for tell us how many numbers\arguments are used. that's why my big problem :(

post how you are calling that function.

see these entire code:

/*−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
SCRNSIZE.C −− Displays screen size in a message box
(c) Charles Petzold, 1998
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−*/
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <string.h>

int CDECL MessageBoxPrintf (TCHAR * szCaption, TCHAR * szFormat, ...)
{
    TCHAR szBuffer [1024] ;
    va_list pArgList ;

    // The va_start macro (defined in STDARG.H) is usually equivalent to:
    // pArgList = (char *) &szFormat + sizeof (szFormat) ;
    va_start (pArgList, szFormat) ;

    // The last argument to wvsprintf points to the arguments
    _vsntprintf (szBuffer, sizeof (szBuffer) / sizeof (TCHAR), szFormat, pArgList) ;

    // The va_end macro just zeroes out pArgList for no good reason
    va_end (pArgList) ;

    return MessageBox (NULL, szBuffer, szCaption, 0) ;
}

int MessageBoxF(char *FormatedText,...)
{
    char text[1024];
    va_list ArgumentList;
    va_start (ArgumentList,FormatedText);
    _vsnprintf(text,sizeof (text) / sizeof (char),FormatedText,ArgumentList);
    va_end(ArgumentList);
    return MessageBox(NULL,text,"hi",MB_OK);
}

double average ( double num, ... )
{
  va_list arguments;                     // A place to store the list of arguments
  double sum = 0;

  va_start ( arguments, num );           // Initializing arguments to store all values after num
  int x = 0;
  for ( x = 0; x < num; x++ )        // Loop until all numbers are added
    sum += va_arg ( arguments, double ); // Adds the next value in argument list to sum.
  va_end ( arguments );                  // Cleans up the list

  return sum / num;                      // Returns the average
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    double a=average(3,10,50,6);
    MessageBoxF("%f",a);
    return 0 ;
}

like you see, i just copy the function from: http://www.cprogramming.com/tutorial/lesson17.html
but the result continues be 0(zero). unless that function isn't correct

line 54 is sending 3 integers, not 3 doubles. Make them doubles and see if that solves the problem.

double a=average(3,10.0,50.0,6.0);

commented: thanks for all +0

yes... works. but why the double don't accept integers?
my code, give me, only, these warning: command line option '-std=c++11' is valid for C++/ObjC++ but not for C [enabled by default]
nothing more

ut why the double don't accept integers?

It has to do with what the compiler pushes on the stack. Integers are 4 bytes on the stack while doubls are 8 bytes. You told va_arg that the parameters are doubles and va_args attempt to get 8 bytes off the stack.

arning: command line option '-std=c++11' is valid for C++/ObjC++ but not for C

Does that file have *.c extension or *.cpp extension.

commented: thanks +0

yes i have the C extension that's why i get that warning.
thanks for all. thanks for correct me. thanks for all

you could change it to *.cpp and eliminate the warning.

thanks.. i did that ;)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.