using SYSTEMTIME structure breaks sscanf -> wtf



  • The interesting part is "VERSION 1" and "VERSION 2" and of course "OUTPUT": IMHO the result of the two versions should be the same, but I found out that it isn't. Has anybody an explanation for that?

    Minimal example, tested on WinXP SP3.

    #include <windows.h>
    #include <tchar.h>
    #include <stdio.h>
    
    int main(int argc, char** argv)
    {
    				SYSTEMTIME temp1, temp2;
    				memset(&temp1, 0, sizeof(SYSTEMTIME));
    				memset(&temp2, 0, sizeof(SYSTEMTIME));
    				unsigned int year = 0;
    				unsigned int month = 0;
    				unsigned int day = 0;
    
    				// VERSION 1
    				if ( (sscanf("20.12.2008", "%2u.%2u.%4u", &day, &month, &year)) != 3 )
    					printf("Error");
    				temp1.wDay = day;
    				temp1.wMonth = month;
    				temp1.wYear = year;
    
    				// VERSION 2
    				if ( (sscanf("20.12.2008", "%2u.%2u.%4u", &(temp2.wDay), &(temp2.wMonth), &(temp2.wYear))) != 3 )
    					printf("Error");
    
    				printf("---->   %u ==? %u\n", temp1.wMonth, temp2.wMonth);
    
    				// OUTPUT is: "---->   12 ==? 0"    --> wtf???
    }
    


  • Hi, SYSTEMTIME members are two-byte words, word aligned, and sscanf returns at least 4 bytes for each %u token. When sscanf is returning temp2.wDay, then wDay and wHour is overwriten.
    So, you'll need to pass temporary integer variables to sscanf, as you did in the first example.
    Or just reorder date string to year.month.day or year.day.month.

    typedef struct _SYSTEMTIME {WORD wYear, wMonth, wDayOfWeek, wDay, ...;
    

    As you see, wYear is the first member, so keep the year as the first member of date string. Sscanf will overwrite wYear and wMonth while parsing/returning the year.



  • sapero schrieb:

    Hi, SYSTEMTIME members are two-byte words, word aligned, and sscanf returns at least 4 bytes for each %u token. When sscanf is returning temp2.wDay, then wDay and wHour is overwriten.
    So, you'll need to pass temporary integer variables to sscanf, as you did in the first example.
    Or just reorder date string to year.month.day or year.day.month.

    typedef struct _SYSTEMTIME {WORD wYear, wMonth, wDayOfWeek, wDay, ...;
    

    As you see, wYear is the first member, so keep the year as the first member of date string. Sscanf will overwrite wYear and wMonth while parsing/returning the year.

    Damn... WORD... of course. The most simple solution. 😃 I normally try to avoid these WORD etc. macros of windows... because I never know what I really get. IMHO that is one additional obfuscation layer that could have been avoided if already the C/C++ designers would have had *well-defined* their variable types (i.e. that "int = 32 bit" would be universally valid) in the past.

    Anyway - thanks a lot! I thought I was going crazy last night.


Anmelden zum Antworten