On 10/31/2008 06:09 PM, Björn Persson wrote:
Many times we don't have a choice. IMHO, C and C++ are still very good programming languages, and all programming languages have thier string and weak points. There used to be an excellent white paper on the HP DSPP site, but I am unable to locate it. (I was the author :-).stan wrote:Jerry Feldman wrote:very poorly written, It's just that simple. From a developer standpoint, developing a portable application, eg. one that can be compiled for 32-bit or 64-bit and work out of the box is relatively simple if you follow some rules. The newer C and C++ language standards also have specific 32-bit and 64-bit integers, so you don't have to use "long" which can be 32-bits or 64-bits. I remember the same issue with 16-bitWould you be willing to point to those 'relatively simple' techniques with a link?No link needed. Just don't make baseless assumptions about sizes of data types. Don't assume that a pointer is the same size as an int for example, or that the number 5000000000 will fit in a long int. Use uint32_t if you need a 32-bit number and so on. It's just that simple.Even better, avoid C and use a better designed language with a good type system.
Here are some suggestions:1. avoid using int, long and longlong. Use int32_t, uint32_t when you specifically want 32-bit and int64_t and utint64_t when you want 64-bits. 2. Use size_t and ssize_t when you are using sizes. These will be the proper width on the platform. remember that the argument to malloc() is size_t, and size_t is returned from strlen() etc. The sizeof is also a size_t.
3. Be very careful of structs: Struct { int foo; long fubar; };In the above struct, foo will always line up on a natural boundary (64-bit or 32-bit). On a 64-bit system, there will be a 32-bit filler between foo and fubar because fubar must line up on a natural boundary (32-bits for a 32-bit system, 64-bits for a 64-bit system). This almost bit me in the ass when I redesigned /etc/utmp for Tru64 Unix so we could use the same physical structure for utmp and utmpx. Fortunately we caught it in time. 4. Time. Historically, time_t in Unix was a signed 32-bit int representing the number of seconds from midnight 1/1/70. It goes negative in 2038. Some systems have converted to 64-bit time_t. Linux was able to adopt the 64-bit time_t quickly, but some commercial Unix systems still support 32-bit time_t. 5. Shifting and shift expressions. I'm going to avoid details here, but in the expression x << y, the expression takes on the type of x, not y. 6. There are some very pathological issues you can get into by combining signed and unsigned:
#include <stdio.h> int main() { long res; int a = -2; unsigned b = 1; res = a * b; printf("Result is %ld\n", res); return 0; }The above C code will erroneously return 4294967294 rather than -2. The reason is that the expression (a * b) is an unsigned expression according to the rules in the C language standard, so that when the result is assigned to res, no sign extension occurs. One solution is to cast the expression as an int, then the sign extension occurs "(int)(a * b)".
Unfortunately, my white paper is no longer accessible on the HP site, but parts of it are in various porting guides. IBM also has some good documents.
-- Jerry Feldman <gaf@xxxxxxx> Boston Linux and Unix PGP key id: 537C5846 PGP Key fingerprint: 3D1B 8377 A3C0 A5F2 ECBB CA3B 4607 4319 537C 5846
Attachment:
signature.asc
Description: OpenPGP digital signature
-- fedora-list mailing list fedora-list@xxxxxxxxxx To unsubscribe: https://www.redhat.com/mailman/listinfo/fedora-list Guidelines: http://fedoraproject.org/wiki/Communicate/MailingListGuidelines