ISO: help porting C code to 64 bit linux platform - Linux

This is a discussion on ISO: help porting C code to 64 bit linux platform - Linux ; I've got a body of C code some of which has run on multiple platforms and some of which has only run on Solaris, until recently. A developer worked at getting the code to compile on 32 bit Linux redhat, ...

+ Reply to Thread
Page 1 of 3 1 2 3 LastLast
Results 1 to 20 of 42

Thread: ISO: help porting C code to 64 bit linux platform

  1. ISO: help porting C code to 64 bit linux platform

    I've got a body of C code some of which has run on multiple platforms
    and some of which has only run on Solaris, until recently. A developer
    worked at getting the code to compile on 32 bit Linux redhat, and that
    appears to be working.

    Now I'm looking at the impact of moving to a 64 bit Linux platform.
    This will be the first time I've ever worked on a 64 bit machine.

    I don't think that, at this time, the code _has_ to be compiled as 64
    bit ... at least, not right away.

    What should I be aware of as I begin compiling code there? Are there
    special flags I will need to use to build things as 32 bit? Should I
    byte the bullet and do the 64 bit port now? And what are some good
    references to read on this topic? I tried to read an article at
    intel.com on porting linux apps to 64 bit intel architecture, but part
    of the document is missing. I'm also reading the Jaeger article on
    porting to 64-bit GNU/Linux Systems. I was just hoping to find as many
    tips as possible. I'm looking at the challenge of 64k lines of library
    without regression tests to verify that things are working properly...


  2. Re: ISO: help porting C code to 64 bit linux platform

    lvirden wrote:
    > I've got a body of C code some of which has run on multiple platforms
    > and some of which has only run on Solaris, until recently. A developer
    > worked at getting the code to compile on 32 bit Linux redhat, and that
    > appears to be working.
    >
    > Now I'm looking at the impact of moving to a 64 bit Linux platform.
    > This will be the first time I've ever worked on a 64 bit machine.
    >
    > I don't think that, at this time, the code _has_ to be compiled as 64
    > bit ... at least, not right away.
    >
    > What should I be aware of as I begin compiling code there? Are there
    > special flags I will need to use to build things as 32 bit? Should I
    > byte the bullet and do the 64 bit port now? And what are some good
    > references to read on this topic? I tried to read an article at
    > intel.com on porting linux apps to 64 bit intel architecture, but part
    > of the document is missing. I'm also reading the Jaeger article on
    > porting to 64-bit GNU/Linux Systems. I was just hoping to find as many
    > tips as possible. I'm looking at the challenge of 64k lines of library
    > without regression tests to verify that things are working properly...


    The most important thing to get is: long != int

    « A programmer should understand the type structure of his language,
    lest great misfortune befall him. Contrary to the heresies espoused by
    some of the dwellers on the Western Shore, `int' and `long' are not the
    same type. The moment of their equivalence in size and representation is
    short, and the agony that awaits believers in their interchangeability
    shall last forever and ever once 64-bit machines become common. »
    -- Henry Spencer

    Use uint32_t and C99 typing conventions as much as possible. Try also to
    read the following articles:
    http://www-128.ibm.com/developerwork...ry/pa-ctypes1/
    http://www-128.ibm.com/developerwork...ry/pa-ctypes2/
    http://www-128.ibm.com/developerwork...ry/pa-ctypes3/
    http://www-128.ibm.com/developerwork...ry/pa-ctypes4/

    Another very common mistake is to cast a pointer to an int... It works
    on 32bits machines but NOT on 64bits ones. Fortunately, this kind of
    problems are almost exhaustively detected by GCC (4.x).

    I must forget tons of other things but these are the most common things
    I got stuck with when playing with my AMD64.

    So, in short:

    1) Start by compiling the code with GCC 4.x, it will already rule out
    quite a lot of problems;

    2) Take a deeper look at the code with types problems in mind

    3) Run it (valgrind is quite helpful to trace all the memory problems)

    That's all folks !!!
    --
    Emmanuel Fleury | Office: 261
    Associate Professor, | Phone: +33 (0)5 40 00 69 34
    LaBRI, Domaine Universitaire | Fax: +33 (0)5 40 00 66 69
    351, Cours de la Libération | email: emmanuel.fleury@labri.fr
    33405 Talence Cedex, France | URL: http://www.labri.fr/~fleury

  3. Re: ISO: help porting C code to 64 bit linux platform

    I forgot something important...

    Emmanuel Fleury wrote:
    >
    > Another very common mistake is to cast a pointer to an int... It works
    > on 32bits machines but NOT on 64bits ones. Fortunately, this kind of
    > problems are almost exhaustively detected by GCC (4.x).


    C99 introduce the uintptr_t type which is quite helpful to fix these
    kind of casts.

    Regards
    --
    Emmanuel Fleury | Office: 261
    Associate Professor, | Phone: +33 (0)5 40 00 69 34
    LaBRI, Domaine Universitaire | Fax: +33 (0)5 40 00 66 69
    351, Cours de la Libération | email: emmanuel.fleury@labri.fr
    33405 Talence Cedex, France | URL: http://www.labri.fr/~fleury

  4. Re: ISO: help porting C code to 64 bit linux platform

    On a sunny day (11 Jan 2007 07:32:10 -0800) it happened "lvirden"
    wrote in
    <1168529529.899614.131060@i39g2000hsf.googlegroups. com>:

    >I've got a body of C code some of which has run on multiple platforms
    >and some of which has only run on Solaris, until recently. A developer
    >worked at getting the code to compile on 32 bit Linux redhat, and that
    >appears to be working.
    >
    >Now I'm looking at the impact of moving to a 64 bit Linux platform.
    >This will be the first time I've ever worked on a 64 bit machine.
    >
    >I don't think that, at this time, the code _has_ to be compiled as 64
    >bit ... at least, not right away.
    >
    >What should I be aware of as I begin compiling code there? Are there
    >special flags I will need to use to build things as 32 bit? Should I
    >byte the bullet and do the 64 bit port now? And what are some good
    >references to read on this topic? I tried to read an article at
    >intel.com on porting linux apps to 64 bit intel architecture, but part
    >of the document is missing. I'm also reading the Jaeger article on
    >porting to 64-bit GNU/Linux Systems. I was just hoping to find as many
    >tips as possible. I'm looking at the challenge of 64k lines of library
    >without regression tests to verify that things are working properly...


    From my limited experience you should replace all 'chars' and 'int's with
    something like uin8_t uint16_t uin32_t etc...
    You should also add
    CFLAGS = -O2 -Wall -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
    to the Makefile.
    The uintXX_t is especially important for header file definitions with
    structures, where you can get wrong parsing if sizes change.
    The -D_FILE_OFFSET_BITS will replace the 32 bit interface in libc with
    the 64 bit one transparently.
    Then watch out you have off_t where it is needed, not some unsigned long
    or something (off_t lseek (int FILEDES, off_t OFFSET, int WHENCE) for example).
    Those things so far did it for me.



  5. Re: ISO: help porting C code to 64 bit linux platform

    Jan Panteltje wrote:
    >
    > From my limited experience you should replace all 'chars' and 'int's with
    > something like uin8_t uint16_t uin32_t etc...


    Are you sure that char size do change ??? I would be a bit surprised...

    > Then watch out you have off_t where it is needed, not some unsigned long
    > or something (off_t lseek (int FILEDES, off_t OFFSET, int WHENCE) for example).
    > Those things so far did it for me.


    Just curious... What does off_t stand for ?

    Regards
    --
    Emmanuel Fleury | Office: 261
    Associate Professor, | Phone: +33 (0)5 40 00 69 34
    LaBRI, Domaine Universitaire | Fax: +33 (0)5 40 00 66 69
    351, Cours de la Libération | email: emmanuel.fleury@labri.fr
    33405 Talence Cedex, France | URL: http://www.labri.fr/~fleury

  6. Re: ISO: help porting C code to 64 bit linux platform

    On a sunny day (Thu, 11 Jan 2007 17:24:13 +0100) it happened Emmanuel Fleury
    wrote in :

    >Jan Panteltje wrote:
    >>
    >> From my limited experience you should replace all 'chars' and 'int's with
    >> something like uin8_t uint16_t uin32_t etc...

    >
    >Are you sure that char size do change ??? I would be a bit surprised...

    It does not in this case, but sure as 64 bits followed 32, we will one day
    see 128 bits.
    I started decades ago with 4 and 8 bit micros, and had my share of
    rewrites.
    Better _always_ specify register size (and if you play FPGA it is a must
    anyways).
    The 'int' and 'char' should be remoevd from C and replaced by xintxx_t
    in my view.


    >> Then watch out you have off_t where it is needed, not some unsigned long
    >> or something (off_t lseek (int FILEDES, off_t OFFSET, int WHENCE) for example).
    >> Those things so far did it for me.

    >
    >Just curious... What does off_t stand for ?


    From libc.info:
    - Data Type: off_t
    This is an arithmetic data type used to represent file sizes. In
    the GNU system, this is equivalent to pos_t' or ong int'.

    If the source is compiled with FILE_OFFSET_BITS == 64' this type
    is transparently replaced by f64_t'.

    - Data Type: off64_t
    This type is used similar to f_t'. The difference is that even
    on 32 bit machines, where the f_t' type would have 32 bits,
    f64_t' has 64 bits and so is able to address files up to 2^63
    bytes in length.

    When compiling with FILE_OFFSET_BITS == 64' this type is
    available under the name f_t'.

    - Macro: _FILE_OFFSET_BITS
    This macro determines which file system interface shall be used,
    one replacing the other. Whereas `_LARGEFILE64_SOURCE' makes the
    64 bit interface available as an additional interface,
    `_FILE_OFFSET_BITS' allows the 64 bit interface to replace the old
    interface.

    If `_FILE_OFFSET_BITS' is undefined, or if it is defined to the
    value `32', nothing changes. The 32 bit interface is used and
    types like `off_t' have a size of 32 bits on 32 bit systems.

    If the macro is defined to the value `64', the large file interface
    replaces the old interface. I.e., the functions are not made
    available under different names (as they are with
    `_LARGEFILE64_SOURCE'). Instead the old function names now
    reference the new functions, e.g., a call to `fseeko' now indeed
    calls `fseeko64'.

    This macro should only be selected if the system provides
    mechanisms for handling large files. On 64 bit systems this macro
    has no effect since the `*64' functions are identical to the
    normal functions.

    This macro was introduced as part of the Large File Support
    extension (LFS).

    So, to make it portable (have it compile correctly) on both 32 and 64 bit
    systems.

    For all I know :-)
    /usr/share/info/libc.info*

    Regards
    Jan

  7. Re: ISO: help porting C code to 64 bit linux platform

    Emmanuel Fleury writes:

    > Jan Panteltje wrote:
    > >
    > > From my limited experience you should replace all 'chars' and 'int's with
    > > something like uin8_t uint16_t uin32_t etc...

    >
    > Are you sure that char size do change ??? I would be a bit surprised...


    As long as you're doing the work to modify the types to actual sizes,
    might as well do the whole job. No point in waiting for the next
    port, to a platform where char is something other than eight bits.
    --
    Joseph J. Pfeiffer, Jr., Ph.D. Phone -- (505) 646-1605
    Department of Computer Science FAX -- (505) 646-1002
    New Mexico State University http://www.cs.nmsu.edu/~pfeiffer

  8. Re: ISO: help porting C code to 64 bit linux platform

    Joe Pfeiffer writes:

    > Emmanuel Fleury writes:
    >
    >> Jan Panteltje wrote:
    >> >
    >> > From my limited experience you should replace all 'chars' and 'int's with
    >> > something like uin8_t uint16_t uin32_t etc...

    >>
    >> Are you sure that char size do change ??? I would be a bit surprised...

    >
    > As long as you're doing the work to modify the types to actual sizes,
    > might as well do the whole job. No point in waiting for the next
    > port, to a platform where char is something other than eight bits.


    Using the sized types is usually a *bad* idea. If you use plain int
    and long where the exact size is irrelevant, the compiler is free to
    use whatever size is optimal on your CPU. By forcing a particular
    size, the compiler may have to generate extra code to simulate types
    smaller than the size of a CPU register.

    The trick to writing portable code is to never assume anything about
    the size of types other than the intXX_t family. By using the least
    restrictive type that is guaranteed to give correct results, the
    compiler is free to do its job optimally.

    --
    Måns Rullgård
    mru@inprovide.com

  9. Re: ISO: help porting C code to 64 bit linux platform

    On a sunny day (Thu, 11 Jan 2007 19:15:24 +0000) it happened
    =?iso-8859-1?Q?M=E5ns_Rullg=E5rd?= wrote in
    :

    >The trick to writing portable code is to never assume anything about
    >the size of types other than the intXX_t family. By using the least
    >restrictive type that is guaranteed to give correct results, the
    >compiler is free to do its job optimally.


    I think that will get you into trouble.
    The first case is the structures used as template for header files.
    Look at this I found:

    wave_header.h
    typedef unsigned short WORD;
    typedef unsigned long DWORD;

    typedef struct
    { /* header for WAV-Files */
    char main_chunk[4]; /* 'RIFF' */
    DWORD length; /* length of file */
    char chunk_type[4]; /* 'WAVE' */
    char sub_chunk[4]; /* 'fmt' */
    DWORD length_chunk; /* length sub_chunk, always 16 bytes */
    WORD format; /* always 1 = PCM-Code */

    WORD modus; /* 1 = Mono, 2 = Stereo */
    DWORD sample_fq; /* Sample Freq */
    DWORD byte_p_sec; /* Data per sec */
    WORD byte_p_spl; /* bytes per sample, 1=8 bit, 2=16 bit (mono)
    2=8 bit, 4=16 bit (stereo) */
    WORD bit_p_spl; /* bits per sample, 8, 12, 16 */
    char data_chunk[4]; /* 'data' */
    DWORD data_length; /* length of data */
    } wave_header;

    If you port this to 64 bits it will fail, because unsigned long takes more space.
    So if the code uses anything like

    int header_size;
    ....
    in_header[i] = malloc(header_size);
    ....
    a = fread(in_header[i], sizeof(char), header_size, ifptr[i]);
    you read the wrong header parameters on a 64 bit system.

    This is portable however:

    typedef struct
    { /* header for WAV-Files */
    char main_chunk[4]; /* 'RIFF' */
    uint32_t length; /* length of file */
    char chunk_type[4]; /* 'WAVE' */
    char sub_chunk[4]; /* 'fmt' */
    uint32_t length_chunk; /* length sub_chunk, always 16 bytes */
    uint16_t format; /* always 1 = PCM-Code */
    uint16_t modus; /* 1 = Mono, 2 = Stereo */
    uint32_t sample_fq; /* Sample Freq */
    uint32_t byte_p_sec; /* Data per sec */
    uint16_t byte_p_spl; /* bytes per sample, 1=8 bit, 2=16 bit (mono) 2=8 bit, 4=16 bit (stereo) */
    uint16_t bit_p_spl; /* bits per sample, 8, 12, 16 */
    char data_chunk[4]; /* 'data' */
    uint32_t data_length; /* length of data */
    } wave_header;

    (I still have char here as 8 bits, but it need not be, so that should be changed too).

    I know it has been argued here that reading in a structure from a file is _bad_.
    But it is done frequently in code I come across.

    There are more reasons, int has come from 16 bits to 32, and now 64.
    For code efficiency if 16 bits was enough, assigning 64 for the same variable is bloat
    (although in memory addressing it may perhaps in some cases make no difference).

    In the old asm days we used bit flags, now I use int for flags, so my flags will be 64 bit wide
    now for 1 bit, can you spell 'bloat' ;-)


  10. Re: ISO: help porting C code to 64 bit linux platform

    Jan Panteltje wrote:

    > I know it has been argued here that reading in a structure from a file is
    > _bad_. But it is done frequently in code I come across.


    There are lots of wrong code anyway. But is better to take advice from good
    one. Even Microsoft some time code wrote code that assumes int were 2 bytes
    long, thinking that the people in the compiler group will never change that
    to not break his code. They do. (Source: "Writing solid code" by Steve
    Maguire, Microsoft Press). And surely many people do the same telling "Hey,
    even Microsoft do it that way".

    --
    Salu2

  11. Re: ISO: help porting C code to 64 bit linux platform

    Måns Rullgård wrote:

    > Using the sized types is usually a *bad* idea. If you use plain int
    > and long where the exact size is irrelevant


    This makes me curious about something: if size is irrelevant, why
    would I use long? I mean, if I specifically choose long as opposed
    to int, then size must not be irrelevant (except that it better be,
    since for some 10+ years, there has been no difference between them
    in practical terms)

    Which brings me to a more philosophical issue --- how severely broken
    the idea of having a type long is --- the way it is defined (in
    particular, where the rule only requires that its size be greater
    than *or equal* than the size of an int)

    Agreed with your point about prefering int to fixed-size types in the
    general case, though.

    Carlos
    --

  12. Re: ISO: help porting C code to 64 bit linux platform

    Carlos Moreno writes:

    > Måns Rullgård wrote:
    >
    >> Using the sized types is usually a *bad* idea. If you use plain int
    >> and long where the exact size is irrelevant

    >
    > This makes me curious about something: if size is irrelevant, why
    > would I use long? I mean, if I specifically choose long as opposed
    > to int, then size must not be irrelevant (except that it better be,
    > since for some 10+ years, there has been no difference between them
    > in practical terms)


    Several of my computers have 32-bit int and 64-bit long, and the
    64-bit machines are become more common by the day.

    > Which brings me to a more philosophical issue --- how severely broken
    > the idea of having a type long is --- the way it is defined (in
    > particular, where the rule only requires that its size be greater
    > than *or equal* than the size of an int)


    I agree it is a little odd. I suppose there is some historical reason
    for it.

    --
    Måns Rullgård
    mru@inprovide.com

  13. Re: ISO: help porting C code to 64 bit linux platform

    Jan Panteltje writes:

    > On a sunny day (Thu, 11 Jan 2007 19:15:24 +0000) it happened
    > =?iso-8859-1?Q?M=E5ns_Rullg=E5rd?= wrote in
    > :
    >
    >>The trick to writing portable code is to never assume anything about
    >>the size of types other than the intXX_t family. By using the least
    >>restrictive type that is guaranteed to give correct results, the
    >>compiler is free to do its job optimally.

    >
    > I think that will get you into trouble.
    > The first case is the structures used as template for header files.
    > Look at this I found:
    >
    > wave_header.h
    > typedef unsigned short WORD;
    > typedef unsigned long DWORD;
    >
    > typedef struct
    > { /* header for WAV-Files */
    > char main_chunk[4]; /* 'RIFF' */
    > DWORD length; /* length of file */
    > char chunk_type[4]; /* 'WAVE' */
    > char sub_chunk[4]; /* 'fmt' */
    > DWORD length_chunk; /* length sub_chunk, always 16 bytes */
    > WORD format; /* always 1 = PCM-Code */
    >
    > WORD modus; /* 1 = Mono, 2 = Stereo */
    > DWORD sample_fq; /* Sample Freq */
    > DWORD byte_p_sec; /* Data per sec */
    > WORD byte_p_spl; /* bytes per sample, 1=8 bit, 2=16 bit (mono)
    > 2=8 bit, 4=16 bit (stereo) */
    > WORD bit_p_spl; /* bits per sample, 8, 12, 16 */
    > char data_chunk[4]; /* 'data' */
    > DWORD data_length; /* length of data */
    > } wave_header;
    >
    > If you port this to 64 bits it will fail, because unsigned long
    > takes more space. So if the code uses anything like
    >
    > int header_size;
    > ...
    > in_header[i] = malloc(header_size);
    > ...
    > a = fread(in_header[i], sizeof(char), header_size, ifptr[i]);
    > you read the wrong header parameters on a 64 bit system.


    That is a good example of how *not* to write code. *Never*, ever read
    or write a struct directly to/from a file. The compiler is free to
    insert padding wherever it likes in a struct.

    --
    Måns Rullgård
    mru@inprovide.com

  14. Re: ISO: help porting C code to 64 bit linux platform

    Måns Rullgård wrote:

    > [...]
    > Several of my computers have 32-bit int and 64-bit long, and the
    > 64-bit machines are become more common by the day.
    >
    >>Which brings me to a more philosophical issue --- how severely broken
    >>the idea of having a type long is --- the way it is defined (in
    >>particular, where the rule only requires that its size be greater
    >>than *or equal* than the size of an int)

    >
    > I agree it is a little odd. I suppose there is some historical reason
    > for it.


    For quite a while, that was never an issue --- or rather, it was
    the opposite problem: I was teaching C and C++ at the time, and it
    would take me a huge amount of effort to sell people the idea that
    the definition *is not* int = 16-bits and long = 32-bits (which
    was sort of popular belief 10 - 12 years ago). After they had
    understood that, it would take me a while to convince them that
    long could actually be equal to int.

    I have to say, I have a hard time understanding why the == part
    in the rule. Oh well...

    Carlos
    --

  15. Re: ISO: help porting C code to 64 bit linux platform

    Måns Rullgård wrote:
    >
    > That is a good example of how *not* to write code. *Never*, ever read
    > or write a struct directly to/from a file. The compiler is free to
    > insert padding wherever it likes in a struct.


    Somehow, I feel you are both right... but you didn't set properly your
    initial conditions.

    I think that this is true to FORCE variables size when the data are
    coming from outside the program. Typically, in the example of Julián the
    struct describe the structure of a wav file which should be played on
    any type of machine. This is clearly some data imported from outside the
    software and on which the programmer has no control.

    On the other hand, Måns is right for all the variables which are lying
    within the program. It should be define as a coherent data flow without
    relying on the size of it.

    At last, variables which are exported outside of the software must also
    have a known size ('cause they will be imported at some other point).

    That's all folks !
    --
    Emmanuel Fleury | Office: 261
    Associate Professor, | Phone: +33 (0)5 40 00 69 34
    LaBRI, Domaine Universitaire | Fax: +33 (0)5 40 00 66 69
    351, Cours de la Libération | email: emmanuel.fleury@labri.fr
    33405 Talence Cedex, France | URL: http://www.labri.fr/~fleury

  16. Re: ISO: help porting C code to 64 bit linux platform

    Emmanuel Fleury wrote:

    >
    > Are you sure that char size do change ??? I would be a bit surprised...
    >
    >

    I recall working on one C compiler for a DSP chip where ALL standard
    types were 32 bits. So char size can change (whteher it does is another
    thing).


    >
    > Just curious... What does off_t stand for ?

    offset type

    Tim Keck

  17. Re: ISO: help porting C code to 64 bit linux platform

    Emmanuel Fleury writes:

    > Måns Rullgård wrote:
    >>
    >> That is a good example of how *not* to write code. *Never*, ever read
    >> or write a struct directly to/from a file. The compiler is free to
    >> insert padding wherever it likes in a struct.

    >
    > Somehow, I feel you are both right... but you didn't set properly your
    > initial conditions.
    >
    > I think that this is true to FORCE variables size when the data are
    > coming from outside the program. Typically, in the example of Julián the
    > struct describe the structure of a wav file which should be played on
    > any type of machine. This is clearly some data imported from outside the
    > software and on which the programmer has no control.


    The WAV header has a number of fixed-size fields, that is true.
    However, that does not imply that the variables used to hold these
    values inside a program need to have the same size. They need to be
    at least as wide, but it doesn't hurt if they are wider if that makes
    for more efficient code.

    The correct way to handle things like a WAV header is to read one
    value at a time, convert it to the machine endianness (the WAV header
    is always little endiean). Reading the header directly into a struct
    can lead to unpleasant surprises if the compiler inserted padding you
    didn't expect, and you still need to handle endian conversions.

    > On the other hand, Måns is right for all the variables which are lying
    > within the program. It should be define as a coherent data flow without
    > relying on the size of it.
    >
    > At last, variables which are exported outside of the software must also
    > have a known size ('cause they will be imported at some other point).


    Any data going into or out of a program must of course have a defined
    format. Now this format need only exist at the external interface.
    In most situations it is preferable to immediately convert input into
    some more efficient internal format, and convert back on output.

    --
    Måns Rullgård
    mru@inprovide.com

  18. Re: ISO: help porting C code to 64 bit linux platform

    On a sunny day (Fri, 12 Jan 2007 19:25:08 +0000) it happened
    =?iso-8859-1?Q?M=E5ns_Rullg=E5rd?= wrote in
    :

    >Emmanuel Fleury writes:
    >
    >> Måns Rullgård wrote:
    >>>
    >>> That is a good example of how *not* to write code. *Never*, ever read
    >>> or write a struct directly to/from a file. The compiler is free to
    >>> insert padding wherever it likes in a struct.


    I have to still see that happen in gcc, do you have a code example?

    >The WAV header has a number of fixed-size fields, that is true.
    >However, that does not imply that the variables used to hold these
    >values inside a program need to have the same size. They need to be
    >at least as wide, but it doesn't hurt if they are wider if that makes
    >for more efficient code.


    Will create problems too, as then when you write the header back, it may overflow.
    (You cannot put a 64 bit value into a 32 bit register).
    For exampe in a program that concatenates n wave files, the resulting could easily be > 4GB.
    That would require a check and error abort (but you would need that anyways).


    >The correct way to handle things like a WAV header is to read one
    >value at a time, convert it to the machine endianness (the WAV header
    >is always little endiean). Reading the header directly into a struct
    >can lead to unpleasant surprises if the compiler inserted padding you
    >didn't expect, and you still need to handle endian conversions.


    True.



    /* cmp.c a program that demonstates bloat */

    #include
    #include


    #define TRUE 0
    #define FALSE 1


    int compare(int a, int b)
    {

    if(a == b) return TRUE;

    return FALSE;

    }


    int main(int argc, char **argv)
    {
    int a;

    if(argc != 3)
    {
    fprintf(stderr, "Usage: cmp value1 value2\nvalues must be integers\n");

    exit(1);
    }

    a = compare(atoi(argv[1]), atoi(argv[2]) );


    if(a == TRUE) fprintf(stderr, "TRUE\n");
    else fprintf(stderr, "NOT TRUE\n");


    exit(0);
    }

    # gcc -o cmp cmp.c
    # ./cmp 1 2
    NOT TRUE


    Strange example? No:

    NAME
    isalnum, isalpha, isascii, isblank, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit - character
    classification routines

    SYNOPSIS
    #include

    int isalnum(int c);
    int isalpha(int c);
    int isascii(int c);
    int isblank(int c);
    int iscntrl(int c);
    int isdigit(int c);
    int isgraph(int c);
    int islower(int c);
    int isprint(int c);
    int ispunct(int c);
    int isspace(int c);
    int isupper(int c);
    int isxdigit(int c);

    DESCRIPTION
    These functions check whether c, which must have the value of an unsigned char or EOF, falls into a certain character class accord-
    -------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^
    ing to the current locale.

    RETURN VALUE
    The values returned are non-zero if the character c falls into the tested class, and a zero value if not.
    ______^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^

    CONFORMING TO
    ANSI-C, 4.3BSD. isascii() is a BSD extension and is also an SVID extension. isblank() conforms to ISO C99 7.4.1.3. isblank() is
    conforming to IEEE Std 1003.1, 2003, and ISO C99 7.4.1.3.

    -----------------------------------------------------------------------------------


    I remember Z80 asm, where you test the zero flag after substracting 2 16 bit registers,
    takes 3 bytes.
    sbc hl,de


    C is a fun language.

    ;-)

  19. Re: ISO: help porting C code to 64 bit linux platform

    Jan Panteltje writes:

    > On a sunny day (Fri, 12 Jan 2007 19:25:08 +0000) it happened
    > =?iso-8859-1?Q?M=E5ns_Rullg=E5rd?= wrote in
    > :
    >
    >>Emmanuel Fleury writes:
    >>
    >>> Måns Rullgård wrote:
    >>>>
    >>>> That is a good example of how *not* to write code. *Never*, ever read
    >>>> or write a struct directly to/from a file. The compiler is free to
    >>>> insert padding wherever it likes in a struct.

    >
    > I have to still see that happen in gcc, do you have a code example?


    #include
    #include
    #include

    struct pad {
    uint16_t foo;
    uint32_t bar;
    };

    int main(int argc, char **argv)
    {
    printf("%d %d\n", offsetof(struct pad, foo), offsetof(struct pad, bar));
    return 0;
    }

    $ gcc foo.c
    $ ./a.out
    0 4

    See the 2 bytes of padding?

    >>The WAV header has a number of fixed-size fields, that is true.
    >>However, that does not imply that the variables used to hold these
    >>values inside a program need to have the same size. They need to be
    >>at least as wide, but it doesn't hurt if they are wider if that makes
    >>for more efficient code.

    >
    > Will create problems too, as then when you write the header back, it
    > may overflow. (You cannot put a 64 bit value into a 32 bit
    > register). For exampe in a program that concatenates n wave files,
    > the resulting could easily be > 4GB. That would require a check and
    > error abort (but you would need that anyways).


    Forcing a 32-bit integer type would not in any way help this
    situation, or any other.

    >>The correct way to handle things like a WAV header is to read one
    >>value at a time, convert it to the machine endianness (the WAV header
    >>is always little endiean). Reading the header directly into a struct
    >>can lead to unpleasant surprises if the compiler inserted padding you
    >>didn't expect, and you still need to handle endian conversions.

    >
    > True.
    >
    > /* cmp.c a program that demonstates bloat */


    I fail to see the relevance of this to the current discussion.

    > Strange example? No:
    >
    > NAME
    > isalnum, isalpha, isascii, isblank, iscntrl, isdigit,
    > isgraph, islower, isprint, ispunct, isspace, isupper,
    > isxdigit - character classification routines


    [...]

    > DESCRIPTION
    > These functions check whether c, which must have the value of
    > an unsigned char or EOF, falls into a certain character class
    > according to the current locale.


    Did you miss the part about the current locale? The character
    classifications vary between languages/scripts.

    --
    Måns Rullgård
    mru@inprovide.com

  20. Re: ISO: help porting C code to 64 bit linux platform

    On a sunny day (Sat, 13 Jan 2007 11:58:03 +0000) it happened
    =?iso-8859-1?Q?M=E5ns_Rullg=E5rd?= wrote in
    :

    >Jan Panteltje writes:
    >
    >> On a sunny day (Fri, 12 Jan 2007 19:25:08 +0000) it happened
    >> =?iso-8859-1?Q?M=E5ns_Rullg=E5rd?= wrote in
    >> :
    >>
    >>>Emmanuel Fleury writes:
    >>>
    >>>> Måns Rullgård wrote:
    >>>>>
    >>>>> That is a good example of how *not* to write code. *Never*, ever read
    >>>>> or write a struct directly to/from a file. The compiler is free to
    >>>>> insert padding wherever it likes in a struct.

    >>
    >> I have to still see that happen in gcc, do you have a code example?

    >
    >#include
    >#include
    >#include
    >
    >struct pad {
    > uint16_t foo;
    > uint32_t bar;
    >};
    >
    >int main(int argc, char **argv)
    >{
    > printf("%d %d\n", offsetof(struct pad, foo), offsetof(struct pad, bar));
    > return 0;
    >}
    >
    >$ gcc foo.c
    >$ ./a.out
    >0 4
    >
    >See the 2 bytes of padding?



    OK, I see it, I ran some more tests on code I wrote, maye have to do some re-writing.
    The fun thing is, some has been out there, and been downloaded a thousand times, and
    confirmed OK on 32 and 64 bits....
    I am now trying to see why (I think I was lucky :-) ).
    mm I found why I think, yes, interesting, variables overlap and it works because 2
    zeros then overlap... because of and even number of 16 bit vars in pairs :-)!!
    See why this works:

    #include
    #include
    #include
    #include


    typedef struct pad {
    uint16_t foo;
    uint16_t flup; // <----------------------
    uint32_t bar;
    } defpad;


    int main(int argc, char **argv)
    {
    int header_size;
    defpad *ppad;

    int a;

    fprintf(stderr, "%d %d\n", offsetof(defpad, foo), offsetof(defpad, bar));

    header_size = sizeof(defpad);

    ppad = (defpad *) malloc( sizeof(defpad) );

    ppad -> foo = 0xeeff;
    ppad -> bar = 0xaabbccdd;
    ppad -> flup = 0x1234;

    fprintf(stderr, "header_size=%d\n", header_size);

    a = fwrite(ppad, sizeof(char), header_size, stdout);

    return 0;
    }


    # gcc -o test2 test2.c
    # ./test2 > q
    # xxd -g 0 q
    0000000: ffee3412ddccbbaa ..4.....

    Comes out OK!!! in case of 2 16 bits vars in sequence.

    LOL





    //$ gcc foo.c
    //$ ./a.out
    //0 4










    >I fail to see the relevance of this to the current discussion.


    The discussion was about 32 bits to 64 bits.
    The more bits the more bloat this example is.
    int as return (where a bool is used),
    and int as argument (where a 8 bits char is used).


    >> isalnum, isalpha, isascii, isblank, iscntrl, isdigit,
    >> isgraph, islower, isprint, ispunct, isspace, isupper,
    >> isxdigit - character classification routines

    >


+ Reply to Thread
Page 1 of 3 1 2 3 LastLast