CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

atoi(*s) pointing to where?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Dutch Guy



Joined: 20 Mar 2018
Posts: 21
Location: University of Antwerp

View user's profile Send private message Send e-mail

atoi(*s) pointing to where?
PostPosted: Sat Apr 18, 2020 1:25 pm     Reply with quote

CCS C v5.074

Code:
#include <18f87J50.h>
#fuses   NOWDT,PLL3,NOCPUDIV,HSPLL,NOXINST
#DEVICE PASS_STRINGS=IN_RAM

When atoi(string_pointer) is called the pointer address gets transferred correctly though the dereferencing gives a weird output. I expect to get 35(ASCII'5') and I get 53....
What memory am I referencing to? Isn't the file register and it isn't the program register (bank 0 nor 1)...

Code:
   
char *begin_char_ptr
if((atoi(begin_char_ptr+1)) > (2767 + (int)negative))


The function parameter s in atoi gives ok address (0x02B5) but *s gives a number that is not in my file register memory....
0x02B5 holds 35 and *s shows ans proceeds with 53 in MPLAB watch.

function called defines : signed int atoi(char *s).

I am reading numbers out of a string.

Anyone knows what is happening?
_________________
I just can`t get it all in my head.... But wait, there is a new hole opening up....
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Sat Apr 18, 2020 1:50 pm     Reply with quote

As posted, begin_char_ptr will contain random values.
The begin_char_ptr actual value will be the 16bit value held by the memory
at 0x2B5.
You have declared a pointer, but not actually set it to point to anything...
It needs to be pointed to the string you want it to access.
Dutch Guy



Joined: 20 Mar 2018
Posts: 21
Location: University of Antwerp

View user's profile Send private message Send e-mail

PostPosted: Sat Apr 18, 2020 4:38 pm     Reply with quote

Thanks for the interest again Ttelmah.
I did shorten the posted code. The begin_char_pointer is loaded trough the function parameters in which itoa is used. While debugging it loads s in stdlib.h as 0x02B5(OK). This position holds 35 which is the '5' in my string as i see in the file register window. But when I look at the locals watch and also when mouseover *s it states a value of 53. When I put a '6' on the position 02B5 *s returns 54, a '1' returns 49 ...consistently. When I change the value of the position the itoa responds to it. 0x02b5 unchanged.
List of mapping(expected) : '1' = 49(31); '2' =50(32); '3'=51(33) ....
So it seems an offset of 28 ??? If i'd hypothetically change the *s=(*s-28)
in stdlib it would work but truely ugly.

Code:

struct rtn sint16_atoi(char *begin_char_ptr, unsigned int digits,short negative)  // declaring return of function in a struct c_s fashion
{
   struct rtn C_S_ATOI;
   signed int16 intercalc;

   *(begin_char_ptr + digits) = '\0';

   if (digits == 5)
   {
      if((atoi(begin_char_ptr+1)) > (2767 + (int)negative))    //convert last 4 and check for > 2767 / -2768 
      {
         if(*begin_char_ptr <= '2')
         {
            intercalc = atoi(begin_char_ptr);
         }
            else
         {
            return(0);
         }      
      }
      else if(*begin_char_ptr <= '3')
      {
         intercalc = atoi(begin_char_ptr);
      }   
      else
         return(0);
   
   }
   else if (digits < 5)
   {
      intercalc = atoi(begin_char_ptr);
   }

   if(negative)
      intercalc |= 0x8000;   //ORmask neg bit 15
   
   C_S_ATOI.value.s_value = intercalc;

   return (C_S_ATOI);
}


Already holding my hand close to my head for a "stupid slap" Smile
_________________
I just can`t get it all in my head.... But wait, there is a new hole opening up....
Dutch Guy



Joined: 20 Mar 2018
Posts: 21
Location: University of Antwerp

View user's profile Send private message Send e-mail

PostPosted: Sat Apr 18, 2020 4:50 pm     Reply with quote

This is the weirdest thing I saw in a while.
How can I post the printscreen png of my environment with watch windows and mouseover?

If I see mouseover 's' as 0x02B5 and I look at the file register then *s must be that value correct? If I change the 4th digit in my sent string then the value changes relatively with 28 offset...
_________________
I just can`t get it all in my head.... But wait, there is a new hole opening up....
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Sun Apr 19, 2020 12:40 am     Reply with quote

I think the big reason you are getting confused is numeric.

53 is 35......

35_hex_ is 53 in base 10.

You have different numeric formats selected for different parts of the
debugger.

Result confusion.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Sun Apr 19, 2020 2:34 am     Reply with quote

As a further comment, are you using a PIC24/30/33?.
If not, for a 5 digit number you need to be using atol, not atoi.
Dutch Guy



Joined: 20 Mar 2018
Posts: 21
Location: University of Antwerp

View user's profile Send private message Send e-mail

PostPosted: Sun Apr 19, 2020 5:33 am     Reply with quote

Not slapping myself yet Smile
The device I'm using is a Clicker 2 board with a 18F87J50. I got tempted to use the ATOL() even with the 8 bit device. I was trying to check the number being in the -32768-32767 range before calling ATOI so I can send an err_rsp before a non signed int16 is put trough to convert. In my program it can be max 5 number-digits with a while(isdigit() && n<5) routine.

But I'm sure you know the feeling of trying it your way first ending with something hopefully working and several self inflicted head injuries Smile Messing around is an excellent way of getting better in CCSC without using a driver at first attempt.

I'm digging in to the dec-hex problem now. Still not sure how atoi has reference problems. I'm also using strcpy, memcmp, strlen and strchr all passing their pointer and char value correctly regarding the file register window.

All is tested/stepped working up to the ATOI conversion. That's where I'm stuck now.
I copied some essentials out of my code, could be I missed some. Now I have also a strange feeling having also defined c as a global in the past.
Shocked

The guide through is : USB_handler called -> command_len = command_checker(extracted_command) returns (int len) -> command_handler()

Code:

//header
void clear_USB_command_buffer();//   
void USB_handling();//
void command_handler(unsigned int,signed int);

enum {NONE,EJECT,UP,DOWN,BELT,STATUS}command_id = 0;

unsigned int command_checker(char *);

#define      MAX_COMMANDS   7
#define      MAX_COMMAND_LENGTH   10
char command_list[][MAX_COMMAND_LENGTH] ={"NONE","EJECT","LOAD","UP","DOWN","BELT","STATUS"};

struct rtn   //returnstruct
{
   short OK;
   union value
   {
      signed int s_value;
      unsigned int u_value;
   };
};

struct rtn sint16_atoi(char *, unsigned int ,short );

//globals:

char c;
char OK[4] = "OK ";
char Ack_Packet_IN[13] = "Command_IN:";
char incoming_FIFO[FIFO_LENGTH];
//unsigned int   last_FIFO_pos;
short new_incoming_command;
unsigned int8    start_FIFO_pos,last_FIFO_pos;
short command_to_echo;

//USB code:
void USB_handling()
{
   if (usb_enumerated())
    {
//      unsigned int len = 0;
      while (usb_cdc_kbhit())
         {
         if(!new_incoming_command)
         {
            last_FIFO_pos = start_FIFO_pos = (last_FIFO_pos + 1)%FIFO_LENGTH;
         }            
         else
         {
            last_FIFO_pos = (last_FIFO_pos+1)%FIFO_LENGTH;   // go around 64 positions
         }
         new_incoming_command = 1;
           c = usb_cdc_getc();
         incoming_FIFO[last_FIFO_pos] = c;
      }
      
      char extracted_command[32];
      (last_FIFO_pos++)%FIFO_LENGTH;         
      incoming_FIFO[last_FIFO_pos] = '\0';
      strcpy(extracted_command,(incoming_FIFO + start_FIFO_pos));
      
      if(new_incoming_command)
      {
         unsigned int command_len = command_checker(extracted_command);
   
         if (command_to_echo)
         {
            short command_var1_ok = 0;
            signed int s_comvar_1;      //signed comm value 1
         
            if(command_len)
            {
               usb_cdc_puts(extracted_command);
               delay_ms(1);
               usb_cdc_putc('\n');
               usb_cdc_putc(0x0D);
            
               int *command_char_ptr = (strchr((extracted_command+command_len),' '));
               int *begin_ptr = command_char_ptr;
   
               for(int n = 0;(*command_char_ptr ==' ') && n < 8;n++)
               {
                  command_char_ptr++;         // SKIP UP TO 8 SPACES
                  begin_ptr++;
               }
               int digit_count = 0;
               short negative;
               if (*command_char_ptr == '-')   //check for negative
               {   
                  negative = 1;
                  command_char_ptr++;
                  begin_ptr++;
               }
               else
                  negative = 0;            
   
               while(isdigit(*command_char_ptr) && digit_count < 6)   // check up to 5 digits
               { 
                  digit_count++;
                  command_char_ptr++;
               }
               struct rtn c_s_1;      
                              // come out with number of digits and sign
               c_s_1 = sint16_atoi(begin_ptr,digit_count,negative);   //declaration of struct element

               if (c_s_1.OK )
               {
                  command_var1_ok = 1;
                  s_comvar_1 = c_s_1.value.s_value;
               }
               else
               {
                  command_var1_ok = 0;
                  s_comvar_1 = 0;   
               }
         
               command_handler(command_id,s_comvar_1);
//               command_to_echo= 0;
            
            }                  //command length END
            else//no command length
            {
               usb_cdc_puts(command_list);
               delay_ms(1);
               usb_cdc_putc('\n');
               usb_cdc_putc(0x0D);
//               command_to_echo= 0;         
            }
         command_to_echo= 0;
         }                     //command to echo END
      new_incoming_command = 0;
      }                        //new_incoming END
   }                           //enumerated END
}                              //USB handling END

unsigned int command_checker(char *command_str)      //returns command length if match, else 0
{
   char *command_list_ptr;   //defines empty 8 bit spaces with a pointer index
   
         
         usb_cdc_puts(Ack_Packet_IN);
         delay_ms(1);
         command_list_ptr = &command_list[0];   //seemed wrapping of commandlist with element 0 and referencer is needed. TEST LATER
         for(unsigned int i = 0 ; i <= MAX_COMMANDS && *(command_list_ptr) != '\0'; i++)
         {
            int c_len = strlen(command_list_ptr);

            if(!memcmp(command_str,command_list_ptr,c_len) && (*(command_str+c_len) == ' ' || *(command_str+c_len) == '\0') )
            {
               command_to_echo = 1;
               command_id = i-1;
               return(c_len);
            }
            command_list_ptr += MAX_COMMAND_LENGTH;   
         }
         command_id = 0;
         command_to_echo = 1;
      
         return(0);
      
}

void command_handler(unsigned int id,signed int handler_com_var1)
{
switch (id)
   {
   case 1 :   //EJECT
      bit_set(EJECT_REQ);
      command_id = 0;
   break;
   case 2 :   // put glass on belt
      bit_set(LOAD_REQ);
      command_id = 0;
   break;
   case 3 :
      bit_set(UP_REQ);
      command_id = 0;
   break;
   case 4 :
      bit_set(DOWN_REQ);
      command_id = 0;
   break;
   case 5 ://belt
      if(handler_com_var1 < 0)
      {
         if(bit_test(DIR_BELT_COIL))
         {
            bit_set(BELT_DIR_TOGGLE_REQ);
            if(!bit_test(RUN_BELT_COIL))
               bit_set(BELT_RUN_TOGGLE_REQ);
         }
      }
      else if((handler_com_var1 > 0))
      {
         if(!bit_test(DIR_BELT_COIL))
         {
            bit_set(BELT_DIR_TOGGLE_REQ);
            if(!bit_test(RUN_BELT_COIL))
               bit_set(BELT_RUN_TOGGLE_REQ);
         }
      }
      else
      {
      if(bit_test(RUN_BELT_COIL))
         bit_set(BELT_RUN_TOGGLE_REQ);
      }
      command_id = 0;
   break;
   case 6 ://belt
   break;

   default:
      command_id = 0;
   break;

   }   //switch id END
}      //command handler end

struct rtn sint16_atoi(char *begin_char_ptr, unsigned int digits,short negative)  // declaring return of function in a struct c_s fashion
{
   struct rtn C_S_ATOI;
   signed int16 intercalc;

   *(begin_char_ptr + digits) = '\0';

   if (digits == 5)
   {
      if((atoi(begin_char_ptr+1)) > (2767 + (int)negative))    //convert last 4 and check for > 2767 / -2768 
      {
         if(*begin_char_ptr <= '2')
         {
            intercalc = atoi(begin_char_ptr);
         }
            else
         {
            return(0);
         }      
      }
      else if(*begin_char_ptr <= '3')
      {
         intercalc = atoi(begin_char_ptr);
      }   
      else
         return(0);
   
   }
   else if (digits < 5)
   {
      intercalc = atoi(begin_char_ptr);
   }

   if(negative)
      intercalc |= 0x8000;   //ORmask neg bit 15
   
   C_S_ATOI.value.s_value = intercalc;

   return (C_S_ATOI);
}

_________________
I just can`t get it all in my head.... But wait, there is a new hole opening up....
Dutch Guy



Joined: 20 Mar 2018
Posts: 21
Location: University of Antwerp

View user's profile Send private message Send e-mail

PostPosted: Sun Apr 19, 2020 5:52 am     Reply with quote

Yes Ttelmah you are right again. My itoa is failing because of something else. I just discovered that the mouseover results in decimal values. I really got fixed on this as being an error.

Thanks
_________________
I just can`t get it all in my head.... But wait, there is a new hole opening up....
Dutch Guy



Joined: 20 Mar 2018
Posts: 21
Location: University of Antwerp

View user's profile Send private message Send e-mail

PostPosted: Sun Apr 19, 2020 6:44 am     Reply with quote

And it got completely clear now I see that int result variable in itoa is only 8-bit.
I_to_l it is. Flips at 128 Embarassed
Switching between int definitions and processors will keep haunting me.
_________________
I just can`t get it all in my head.... But wait, there is a new hole opening up....
Dutch Guy



Joined: 20 Mar 2018
Posts: 21
Location: University of Antwerp

View user's profile Send private message Send e-mail

PostPosted: Sun Apr 19, 2020 7:05 am     Reply with quote

Its working fully now.

My end question is : What would be best ?
- First checking for last 4 digits to be under the +276-278 range and checking the 5th digit for being 3 or lower before feeding the A_TO_L.

or

-Converting with A_to_I32 and then checking the int32 for being withing 32767 to -32768 range.

This is what I had in mind in the beginning, I was only confused again atoi being 8 bit and not 16.
_________________
I just can`t get it all in my head.... But wait, there is a new hole opening up....
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Apr 19, 2020 8:17 am     Reply with quote

OK, please humour me......

You've got a 5 character string ( ASCII) xxxxx and you want to know if it's less than 32767
so... wouldn't a set of simple compare tests, in the right sequence work better or faster ?

consider when a[5] = '32767'
....
if a[4] =>4 //too big ( 4xxxx)
then
if a[3] =>3 //too big ( 33xxx)
then
if a[2] =>8 //too big ( 328xx)
.....

Ok I'm NOT a C programmer, just trying to thing of an easier way to do the test as I assume atoi are 'big' functions....size and execute.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Sun Apr 19, 2020 1:17 pm     Reply with quote

If the strings are purely 'numbers', without any of the formatting
supported by atol (no hex or binary), and are always +ve, it is actually
significantly faster and smaller to go 'DIY'.
Code:

#inline
unsigned int16 times10(unsigned int16 val)
{
    return (val*8+val*2);
} //this is significantly more efficient than a standard *10.

unsigned int16 asctoul(char * string)
{
    byte chr;
    unsigned int16 result=0;
    chr=*(string++);
    while (chr!=0 && chr!=13) //LF or NUL terminates
    {
        if (chr==' ')
           continue; //ignore spaces
        chr=chr-'0'; //ascii to binary
        result=times10(result);
        result+=chr; //add in the digit
        chr=*(string++);         
    }
    return result;
}


You may be surprised at how much faster this is than atol.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group