Thread: Casting strings to integers and back

  1. #1
    Registered User
    Join Date
    Dec 2001
    Posts
    40

    Casting strings to integers and back

    Can anyone explain why this is happening. First I will include the code that I am running.

    Code:
    #include <stdio.h>
    
    int main(void)
    {
    char var1[4] = "FP10";
    int var2 = 0;
    
    printf("Value of var1 is %s\n", var1);
    printf("Vaue of var2 is %d\n", var2);
    
    memcpy(&var2, &var1, sizeof(var2));
    
    printf("Vaue of var2 is %d\n", var2);
    printf("String value of var2 is %s\n", &var2);
    The output from this is:

    Value of var1 is FP10
    Value of var2 is 0
    Value of var2 is 1179660592
    String value of var2 is FP10FP10

    Lines 1 and 2 are as you would expect, it is lines 3 and 4 that I did not get what i expected. I thought that the display of the value of var2 would show the ascii codes concatenated together and why is the string value displaying twice?
    Thanks
    Last edited by clancyPC; 11-19-2003 at 06:05 AM.

  2. #2
    .
    Join Date
    Nov 2003
    Posts
    307
    String functions expect ASCII zero (null-termination) at the end strings. var1 is too short by one byte and is not null-terminated.
    Code:
    #include <stdio.h>
    #include <string.h>
    int main(int argc, char *argv[])
    {
       char var1[5] = {'\0'};
       int var2 = 0;
       strcpy(var1,"FP10");
       printf("Value of var1 is %s\n", var1);
       printf("Vaue of var2 is %d\n", var2);
    
       memcpy(&var2, &var1, sizeof(var2));
    
       printf("Vaue of var2 is %d\n", var2);
       printf("String value of var2 is %s\n", &
       return 0;
    }
    You can do the same thing with a union.

    Code:
    union{
       char var1[5];
       int var2;
       } u;
       
       strcpy(u.var1,"FP10");
       printf("Value of u.var1 is %s\n", u.var1);
       printf("Vaue of u.var2 is %d\n", u.var2);
       return 0;
    Last edited by jim mcnamara; 11-19-2003 at 06:27 AM.

  3. #3
    Registered User
    Join Date
    Dec 2001
    Posts
    40
    Thank you,
    I did have a variation that had the string null terminated, but it did not make any difference. The output was the same for both cases.
    The union does work, but I suppose what I was really hoping for was an explanation of the behaviour that I am seeing.
    To put it into context, I am trying to understand a piece of legacy code as to why it is working the way that it is. The code does pretty much what my example does. It copies a string into an integer using a memcpy. The reason why a string is copied into an int is that it then has to go into an integer column in an informix database (its the only one available). There is an informix function, ASCIIN, which and I quote direct from the documentation here, "displays integer fields as N ascii characters". I have read this as: it interprets each byte of the integer and displays the ascii character appropriate to that number. I could be wrong about that. Except that it does not do what it says on the tin, it displays a four digit number instead of four characters. So I am really trying to figure out what is happening at each stage to determine if there is a flaw anywhere that needs fixing, or if what is being attempted is not possible.
    Simple eh.

  4. #4
    .
    Join Date
    Nov 2003
    Posts
    307
    Code:
    char var1[4] = "FP10";
    int var2 = 0;
    (speaking HPUX and C compilers in general) that code above creates a contiguous block of memory in the $DATA segment of the code - one part of the memory allocated to the program where information rather than instructions are stored.

    The initial segment (var1) is null-terminated because a zero int (var2) is 0x00000000 - four ASCII zero characters, 0x00. The zeroes immediately follow the end of var1 in memory - because the size of var1 is four bytes, the compiler does not have to word align (change the position in memory) the next variable, var2. So, var1 is actually null-terminated, even tho it really isn't null-terminated on purpose, like it should be.

    However. When you place a value in var2, the zeroes may go away. printf() uses the "zeroes" to know when to stop printing a string variable "%s" - since the "zeroes" are no longer there, printf() keeps going until it finds a zero ASCII char -- or the program core dumps. Fortunately it finds one.

    You're lucky you don't get a segfault error - or a bus error when printing. Assuming this is unix code. Windows would generate a GPF. DOS & Win 3.1-> likely the blue screen of death.

  5. #5
    Registered User linuxdude's Avatar
    Join Date
    Mar 2003
    Location
    Louisiana
    Posts
    926
    Code:
    union{
       char var1[5];
       int var2;
       } u;
       
       strcpy(u.var1,"FP10");
       printf("Value of u.var1 is %s\n", u.var1);
       printf("Vaue of u.var2 is %d\n", u.var2);
       return 0;
    Could someone give me a valid use for using unions i am on it in my c book that I am reading. I saw a use for bios functions in windows. But what about Linux?? Can you do the same bios function in Windows. thanx in advance

  6. #6
    .
    Join Date
    Nov 2003
    Posts
    307
    working with bit fields is a one use.
    Code:
    char *bitpattern(char ch){             // create a bit pattern string: 0's & 1's
            const char one='1',
                       zero = '0';
            int i;
            extern char *_Workstr;
            extern void bld_workstr(size_t);
            struct bitmap{                         // bitfields for a byte
                  unsigned b7:1;
                  unsigned b6:1;
                  unsigned b5:1;
                  unsigned b4:1;
                  unsigned b3:1;
                  unsigned b2:1;
                  unsigned b1:1;
                  unsigned b0:1;
             };
    
            union bits{                            // allow moving a byte into the bitfields
                    unsigned char ch;
                    struct bitmap x;
            } b;
            for(i=0;i<8;i++)*(_Workstr+i)=zero; // set all the bits to zero for starters
            b.ch = (unsigned)ch;           // move the char into the union
            if(b.x.b7) *_Workstr=one;      // for each bit set, put a '1' in the string
            if(b.x.b6) *(_Workstr+1)=one;
            if(b.x.b5) *(_Workstr+2)=one;
            if(b.x.b4) *(_Workstr+3)=one;
            if(b.x.b3) *(_Workstr+4)=one;
            if(b.x.b2) *(_Workstr+5)=one;
            if(b.x.b1) *(_Workstr+6)=one;
            if(b.x.b0) *(_Workstr+7)=one;
            return _Workstr;
    }

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    >working with bit fields is a one use.

    Important considerations:
    • The value of a union member other than the last one stored into is unspecified behavior*.
      *behavior where th[e] International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance
    • The order of allocation of bit-fields is implementation defined**.
      **unspecified behavior where each implementation documents how the choice is made
    Last edited by Dave_Sinkula; 11-19-2003 at 11:28 PM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  8. #8
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Good observation, Jim.

    Also, memcpy is being used wrong. Since var1 is essentially a pointer, you would do:

    memcpy(&var2, var1, sizeof(var2));

    or even:

    memcpy(&var2, &var1[0], sizeof(var2));

    A safe print mechanism would be:

    Code:
    void print_int(int packed)
    {
     const char * p = (const char*)&packed;
     int i = 0;
     
      for(i = 0; i < 4; i++)
       printf("%c", p[i]);
    }
    Or a more useful:

    Code:
    void print_bytes(void * packed, int length)
    {
     const char * p = (const char*)packed;
     int i = 0;
     
      for(i = 0; i < length; i++)
       printf("%c", p[i]);
    }

    As far as bitfields go, be sure to use your compiler's alignment mechanism, ie:

    Code:
    #pragma pack(push,1)
    struct Byte 
    {
     unsigned int b0 : 1;
     unsigned int b1 : 1;
     unsigned int b2 : 1;
     unsigned int b3 : 1;
     unsigned int b4 : 1;
     unsigned int b5 : 1;
     unsigned int b6 : 1;
     unsigned int b7 : 1;
    };
    #pragma pack(pop)
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. converting string to int back to string
    By thenson in forum C Programming
    Replies: 4
    Last Post: 02-03-2008, 11:21 AM
  2. Array of Ints to a Strings
    By mattAU in forum C Programming
    Replies: 10
    Last Post: 08-17-2006, 05:25 AM
  3. Sorting integers
    By Munkey01 in forum C++ Programming
    Replies: 3
    Last Post: 02-20-2003, 07:36 AM
  4. itoa - going back to char.
    By Ray Schmidt in forum C++ Programming
    Replies: 1
    Last Post: 02-08-2003, 09:54 AM
  5. Printing integers backwards
    By Basia in forum C Programming
    Replies: 8
    Last Post: 06-28-2002, 01:55 PM