|
|
View previous topic :: View next topic |
Author |
Message |
SteveC
Joined: 09 Jul 2004 Posts: 10
|
Is this a bug? It certainly got me |
Posted: Wed Jul 14, 2004 9:45 am |
|
|
Hello,
I'm an infrequent C programmer, and I realise that the use of string constants in CCS C is a no go. During the process of learning this I experienced some mighty strange behaviour. I've condensed the code to show it simply - Look at this:
Code: | #include <16F877.h>
#device ICD=TRUE
#fuses XT,WDT,PUT,NOBROWNOUT
#use delay(clock=4000000, restart_wdt)
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7, RESTART_WDT)
void send_id(char id[10])
{
printf(id);
// Why is the following line executed the same number of times as there are characters in the call to send_id()?
delay_ms(1000);
}
void main() {
setup_counters(RTCC_INTERNAL, WDT_18MS);
// Now for the main loop
do
{
send_id("1234567890");
} while (true); // Stay in the loop forever
} |
I have read the manual where it says:
Quote: | A (non-standard) feature has been added to the compiler to help get around the problems created by the fact that pointers cannot be created to constant strings. A function that has one CHAR parameter will accept a constant string where it is called. The compiler will generate a loop that will call the function once for each character in the string. |
But, why does it call the delay_ms(1000) each time as well? I would argue that my function doesn't have a single CHAR, but an array of 10 CHARs. So, it would be nice if the compiler picked this up, and spat out an error (or a warning?) The CCS statement is ambiguous, I think?
I don't like this behaviour at all - It caused me a lot of head scratching! Is it worth reporting this to CCS, or am I missing something obvious?! I suspect that there are a number of people for whom improved string constant handling within PICC would make life much easier?!
Thanks for reading
Steve. |
|
|
Futureatwork Guest
|
|
Posted: Wed Jul 14, 2004 11:03 am |
|
|
If my understanding is correct, the function that will be called many times is send_id, once for each char...
Try to move the delay_ms to main loop right after the send_id call. |
|
|
Guest
|
|
Posted: Wed Jul 14, 2004 11:21 am |
|
|
Try to use
void send_id(char *id)
Additionally your declaration is wrong: the input string is 11 byte long (10 characters + the terminating zero) |
|
|
Guest
|
Re: Is this a bug? It certainly got me |
Posted: Wed Jul 14, 2004 3:29 pm |
|
|
SteveC wrote: | Hello,
printf(id);
|
It would be program style if you declared your constants elsewhere.
const char ID[]={"1234567890");
Compiler takes care of figuring out how much space to allocate, and it takes care of adding the null also.
Then when you need to send the const string, try
puts(ID);
puts() will handle a const string. puts(0 adds cr/lf
If you only want the string without cr/lf the use a loop with putchar() . |
|
|
Steve H. Guest
|
|
Posted: Wed Jul 14, 2004 6:09 pm |
|
|
This is not a bug - but when you think about it it works exactly like it says it will. Look how CCS declares putc() then write a small program the sub's putc for your function. putc will be called as many times as needed to write the string - Actually this ia a very useful feature of the compiler and has saved me a bunch of time coding up a similar function myself many times.
I agree with guest. Your declarations are wrong, you should check out the declerations and how putc does it.
Steve H. |
|
|
SteveC
Joined: 09 Jul 2004 Posts: 10
|
|
Posted: Thu Jul 15, 2004 3:13 am |
|
|
Thanks for the comments. The program I posted was merely to show the issue in the simplest way possible - It's not the program I'm writing. I actually need to call send_id with a variable, not a constant (the device uses a matrix keypad for id entry which is sent out of the serial port).
I can't use puts, as the CR/LF at the end will mess things up.
I agree that it's a very useful feature - It's just that I didn't know about it! I now understand how it works! (CCS do say that it's a non-standard feature, though!)
I could do it by calling putc from main, and then calling my verify function straight after it, instead of what I was trying to do initially which was to have the send_id function sending and verifying. In fact, I've declared 'id' as a global, so it's no longer an issue.
Steve. |
|
|
Ttelmah Guest
|
|
Posted: Thu Jul 15, 2004 5:23 am |
|
|
SteveC wrote: | Thanks for the comments. The program I posted was merely to show the issue in the simplest way possible - It's not the program I'm writing. I actually need to call send_id with a variable, not a constant (the device uses a matrix keypad for id entry which is sent out of the serial port).
I can't use puts, as the CR/LF at the end will mess things up.
I agree that it's a very useful feature - It's just that I didn't know about it! I now understand how it works! (CCS do say that it's a non-standard feature, though!)
It's now a simple matter of calling putc from main, and then calling my verify function straight after it, instead of what I was trying to do initially which was to have the send_id function sending and verifying.
Steve. |
The 'key' is to understand what happens in main.
The 'send_id' fuction is reached, and a string of constant characters detected. The compiler then automatically switches to the 'fallback' behaviour to handle these, and calls send_id ten times, handing it one character in turn each time. Hence, 'of course' the delay inside the routine is called ten times. If the error checking in the compiler was better there would be a complaint at this point (since a function, that is expecting an 'address' for an array, instead receives a single character). However since the function itself then does nothing with this, except hand the character 'on' to printf, there is no error.
The function is behaving exactly as CCS says it should.
CCS is very 'liberal' about not reporting 'type' errors (which would at least warn you that the layout is wrong), hence it is common practice to run the code through a seperate C 'syntax checker', which will report this as an error, and avoid wasting time. However given the special exemption present in CCS C for this type of construction, such checkers will report the perfectly good construction as 'wrong', leaving it to you to detect the difference between the allowable form, and this mistake...
Best Wishes |
|
|
bennyboos
Joined: 17 Nov 2005 Posts: 30 Location: Chester UK
|
Syntax Checker recommendations |
Posted: Thu Dec 21, 2006 7:18 am |
|
|
Hi Ttelmah,
do you use a syntax checker and if so can you recommend one?
I've recently wasted a day with a very frustrating error whereby I was trying to compare a variable for negativity. My problem was that I had forgotten to declare it as signed (see below) and this made it rather eratic in its behaviour.
Code: |
int16 angle;
// ....
// other lines of code
// ....
do {
// ... other stuff
refreshAngle(&angle);
} while(angle<0);
|
Can you suggest a tool/s that will spot this type of boo boo?
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
|
|
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
|