I have a portable program which uses ssize_t under the assumption it is a signed integer. Conceptually it does something like:
#include <stdint.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
size_t size_10 = 10;
size_t size_20 = 20;
ssize_t len_diff;
len_diff = (ssize_t)size_10 - (ssize_t)size_20;
if (len_diff < 0)
printf("negative\n");
else if (len_diff > 0)
printf("positive\n");
else
printf("zero\n");
}
One would expect the program to print 'negative' but instead it prints 'positive'. The reason is easy to see from how ssize_t is defined (in sourceannotations.h):
#ifndef _SSIZE_T_DEFINED
#ifdef _WIN64
typedef unsigned __int64 ssize_t;
#else
typedef _W64 unsigned int ssize_t;
#endif
#define _SSIZE_T_DEFINED
#endif
And so, subtracting two unsigned values results in an unsigned value and hence the result.
In older versions of the Windows SDK (e.g. V7.0A) the ssize_t was correctly defined as:
//
// SIZE_T used for counts or ranges which need to span the range of
// of a pointer. SSIZE_T is the signed variation.
//
typedef ULONG_PTR SIZE_T, *PSIZE_T;
typedef LONG_PTR SSIZE_T, *PSSIZE_T;
Can anyone explain this change? Are we supposed to stop using ssize_t on Windows?
Update: Based on all the answers, it appears to be a bug in Visual Studio 2010 which includes ssize_t but defined incorrectly. This is a sneaky and nasty bug.
Last Update: This bug has been fixed in VS2012 and VS2016. Also from the comment discussion it appears that this way of calculating len_diff is problematic when the values compared are of different signs when casted to SSIZE_T
Would this be a good solution?
#if defined(_MSC_VER)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
ssize_t
is not standard C, it is a typedef from Posix. That you found it in a code analysis header for VS2010 probably has something to do with the origin, most code analysis tooling started on Unix. It is removed again in VS2012 and up.
That it is present in the BaseTsd.h SDK file in all caps certainly is not a mistake, Windows supported a Posix subsystem. These typedefs insulate the operating system from compiler implementation details, the basic reason that Windows managed to survive architecture changes, moving from 16 to 32 to 64-bit.
So the real problem is that you are trying to compile a Posix program on Windows but without using Posix headers. Trivial to solve, just add your own typedef before the #includes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With