views:

83

answers:

4

I have a program I am trying to debug, but Dynamic C apparently treats strings differently than normal C does (well, character arrays, anyway). I have a function that I made to make an 8 character long (well, 10 to include the \0 ) string of 0s and 1s to show me the contents of an 8-bit char variable. (IE, I give it the number 13, it returns the string "0001101\0" )

When I use the code below, it prints out !{happy face] 6 times (well, the second one is the happy face alone for some reason), each return comes back as 0xDEAE or "!\x02.

I thought it would dereference it and return the appropriate string, but it appears to just be sending the pointer and attempting to parse it. This may seem silly, but my experience was actually in C++ and Java, so going back to C brings up a few issues that were dealt with in later programming languages that I'm not entirely sure how to deal with (like the lack of string variables).

How could I fix this code, or how would be a better way to do what I am trying to do (I thought maybe sending in a pointer to a character array and working on it from the function might work, but I thought I should ask to see if maybe I'm just trying to reinvent the wheel).

Currently I have it set up like this:

this is an excerpt from the main()

display[0] = '\0';
for(i=0;i<6;i++)
{
     sprintf(s, "%s ", *char_to_bits(buffer[i]));
     strcat(display, s);
}
DispStr(8,5, display);

and this is the offending function:

char *char_to_bits(char x)
{
     char bits[16];
     strcpy(bits,"00000000\0");
     if (x & 0x01)
         bits[7]='1';
     if (x & 0x02)
         bits[6]='1';
     if (x & 0x04)
         bits[5]='1';
     if (x & 0x08)
         bits[4]='1';
     if (x & 0x10)
         bits[3]='1';
     if (x & 0x20)
         bits[2]='1';
     if (x & 0x40)
         bits[1]='1';
     if (x & 0x80)
         bits[0]='1';
     return bits;
}

and just for the sake of completion, the other function is used to output to the stdio window at a specific location:

void DispStr(int x, int y, char *s)
{
     x += 0x20;
     y += 0x20;
     printf ("\x1B=%c%c%s", x, y, s);
}
+2  A: 
char * func()
{
  char *str = malloc (string_size * sizeof(char));
  strncpy (str, "Hello World", string_size);
  return str;
}


main()
{
  char *str = func();
  printf ("%s\n", str);
  free(str);
}
Tom Dignan
i realized you're using something called dynamic c, but this is guaranteed to work in any C implementation that adheres to the c89/99 standards. you should check malloc though. also, if you aren't using something special, any arrays you declare inside functions will be on automatic storage and not returnable.. so I assume that's what dynamic C is letting you do that I didn't know about. sounds cool
Tom Dignan
+1  A: 

Your problem is that char bits[16]; is local to the char_to_bits function, so on return it is pointing to an invalid stack location. You should pass in the buffer you want filled with the string. Like so:

char * char_to_bits(char x, char * bits)
{
     strcpy(bits,"00000000\0");
     ...
     return bits;
}

and the call like so:

 char bits[16];
 sprintf(s, "%s ", char_to_bits(buffer[i], bits));

In this regard, Dynamic C (this?) is behaving just like C here. It's a common mistake made by people used to Java/C++ strings. A C "string" is merely pointer to data, not an object.

invariant
Yeah, that seems to be my issue. I am still very in the C++/Java mindset, so I think of strings as an object that can be returned, as opposed to just a pointer to the first element of the character array.This version worked beautifully for what I was trying to do.I did try this in lcc-win32, and it seemed to work fine with just the char *char_to_bits(char x) instantiation, but for some reason it reacted differently in the Dynamic C.And yeah, it is that program, I'm using it to program one of their single board computers, and adding some debugging functionality with this.
aquanar
Cool. Depending on the compiler/architecture, the string may still be there at the address pointed to after the function returns, depends whether the stack has been overwritten by something else or not. Different compilers will do things idfferently, may use registers instead of stack for things etc. This might explain the varying behaviour.
invariant
A: 

The problem might be the fact that your bits[] array from char *char_to_bits(char x) is declared locally, declare it globally.

Please try this program, I tested it using both Mingw and Borland/CodeGear compilers and it works:

#include <stdio.h>
#include <string.h>

using namespace std;

//Declare bits[] globaly
char bits[16];

//Your char to bit funtion
char* char_to_bits(char x)
{

     strcpy(bits,"00000000\0");
     if (x & 0x01)
         bits[7]='1';
     if (x & 0x02)
         bits[6]='1';
     if (x & 0x04)
         bits[5]='1';
     if (x & 0x08)
         bits[4]='1';
     if (x & 0x10)
         bits[3]='1';
     if (x & 0x20)
         bits[2]='1';
     if (x & 0x40)
         bits[1]='1';
     if (x & 0x80)
         bits[0]='1';
     return bits;
}

int main()
{
    //Testing char_to_bits() by writing word "Test" in binary

    char test[] = "Test";

    for(int i = 0; i < strlen(test); i++)
    {
        printf("%s ", char_to_bits(test[i]));
    }

    return 0;
}
Dr.Optix
I don't think it's a good idea to declare it globally. Better to declare it in main().
invariant
Well yeah, but now it depends on how complex the application is.
Dr.Optix
+4  A: 

Here are the problems I can see:

  • Function char_to_bits returns the char array bits which is local. So its memory will be lost once the function returns. To solve this allocate memory for bits dynamically using malloc and later free it using the function free or you can make it static or declare bits globally.
  • You need not dereference the call to char_to_bits in the sprintf. So change
    sprintf(s, "%s ", *char_to_bits(buffer[i]));

    to

    sprintf(s, "%s ", char_to_bits(buffer[i]));

codaddict