C language FOR Loop ending condition

Thread Starter

eblc1388

Joined Nov 28, 2008
1,543
Hi all, need some help in understanding the following.

In the following C code, pString is a normal character string ended with null and is passed as pointer into the SendString function, which extracts one byte and calls the SerialOut_To_PC function.

How does the FOR loop inside the SendString function knows when to stop? Or how to interpret *a as an ending condition?

Rich (BB code):
//*******************************
// RS232 Send string (unsigned)
//*******************************
void SendString(unsigned char* pString)
{
 unsigned char *a;

 for(a=pString;*a;a++)
    SerialOut_To_PC(*a); 
}

// This is how the SendString is called to send the string in quotes

SendString("ABCDE_MNOPQ\0");
 
Last edited:

someonesdad

Joined Jul 7, 2009
1,577
A for loop continues while the second expression evaluates to true. The loop will end when *a = 0; i.e., you reach a null character.
 

hgmjr

Joined Jan 28, 2005
9,029
I believe the explicit null character \0 at the end of your string is redundant. The C compiler appends a null character when the string is stored in memory.

It is the null character that terminates the processing of the string. However, I think that a better means of coding the FOR loop would be to use the LEN() function to define the length of your string.

Example: for(a=pString;strlen(pString);a++)

You will need to include the header file "string.h" to make the function call to strlen() available.


hgmjr
 
Last edited:

Thread Starter

eblc1388

Joined Nov 28, 2008
1,543
A for loop continues while the second expression evaluates to true. The loop will end when *a = 0; i.e., you reach a null character.
That's it. Thanks.

hgmjr said:
I believe the explicit null character \0 at the end of your string is redundant. The C compiler appends a null character when the string is stored in memory.
Yes, the compiler should automatically append a \0 to a string constant.

I'm just reading through codes by others. Perhaps the author places one more NULL in order to be sure, just in case.

Thanks again, gentlemen.
 

Papabravo

Joined Feb 24, 2006
12,301
I believe the explicit null character \0 at the end of your string is redundant. The C compiler appends a null character when the string is stored in memory.

It is the null character that terminates the processing of the string. However, I think that a better means of coding the FOR loop would be to use the LEN() function to define the length of your string.

Example: for(a=pString;strlen(pString);a++)

You will need to include the header file "string.h" to make strlen avaliable.


hgmjr
As written this loop would be infinite since tha value of pString is not changed therefore strlen(pString) would always evaluate to a non zero constant for any non-null string pointed at by pString. You could fix the problem by saying
Rich (BB code):
for(a=pString; strlen(a); a++)
This requires a function call and some considerable processing at each iteration of the loop. In the evaluation of expressions there is an implicit test for zero (FALSE) or non-zero (TRUE), but you can always improve the clarity of your code by making the comparison explicit as in
Rich (BB code):
for(a=pString; *a != '\0'; a++)
This method has the advantage of being both clear and effcient.

Many people actually use the macro preprocessor to #define the following:
Rich (BB code):
#define FALSE  0
#define TRUE   !0
 

THE_RB

Joined Feb 11, 2008
5,430
...
Rich (BB code):
//*******************************
// RS232 Send string (unsigned)
//*******************************
void SendString(unsigned char* pString)
{
 unsigned char *a;

 for(a=pString;*a;a++)
    SerialOut_To_PC(*a); 
}
That's clumsy for a heap of reasons. pString is already a temporary variable that has cost RAM so there no need to copy it to another temp var. You could do this;

Rich (BB code):
//*******************************
// RS232 Send string (unsigned)
//*******************************
void SendString(unsigned char* pString)
{
  while(*pString)
  {
    SerialOut_To_PC(*pString); 
    pString++;
  }
}
That saves 2 RAM (by removing the need for a 16bit pointer) but the compiler will still be doing the indirect addressing twice so it will still be slow like the example above it.

Rich (BB code):
//*******************************
// RS232 Send string (unsigned)
//*******************************
void SendString(unsigned char* pString)
{
  unsigned char temp;
  while(1)
  {
    temp = *pString;
    if(temp) SerialOut_To_PC(temp); 
    else break;    
    pString++;
  }
}
This costs 1 RAM but only needs to do the indirect addressing once and then tests and passes only a char var so it will be much faster executing and smaller code than either example especially on a microcontroller (which is probable considering the "Serial_out_to_PC").
 

AlexR

Joined Jan 16, 2008
735
Given that any half-decent compiler will perform extensive optimisation you may as well write your source as clearly and concisely as possible and leave it up to the compiler of turn it into efficient code.
You will probably find that even though your source uses pointers the compiler will translate these to direct addressing in the final assembly version of the code so personally I would go with you #2 option.
I.E.
Rich (BB code):
void SendString(unsigned char* pString)
{
  while(*pString)
  {
    SerialOut_To_PC(*pString); 
    pString++;
  }
}
 
Top