Journal Articles

CVu Journal Vol 11, #6 - Oct 1999 + Letters to the Editor
Browse in : All > Journals > CVu > 116 (22)
All > Journal Columns > LettersEditor (132)
Any of these categories - All of these categories

Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xt and user-summary-[publicationtype].xt. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles . The templates will get the extension .xt there.

Title: You Write, the Editor Replies

Author: Administrator

Date: 06 October 1999 13:15:33 +01:00 or Wed, 06 October 1999 13:15:33 +01:00

Summary: 

Body: 

Dear Francis,

Further to my critique of the ISBN code, I found a routine in Ivor Horton's Beginning Visual C++ 6 (Wrox) which will delete dashes from a string without using functions from the standard library.

void removeDashes(char * foo) {
  int i=0;     /* copy to offset within string     */
  int j=0;     /* copy from offset within string   */
  while (( *(foo + i) = *(foo + j++)) != '\0')
    if (*(foo + i) != '-')  i++;
  return;
}

I think I would prefer to code that function like this:

char[] removedashes(char  sourcestring[]) {
int i=0;     /* index of destination in string     */
int j=0;     /* index of source in string   */
while ( sourcestring[i] ==  sourcestring [++ j]) 
  if (sourcestring[i] != '-') ++i;
return sourcestring;
}

Note that we do not need to compare the value of the assignment with the nul character. What do the readers think? How about writing a function to remove all instances of the chars given in one string from a second string. Implement the following prototype:

char[] eliminate(char these[], char from[]);

Here are some thoughts on the i+=++i challenge from C Vu 11.5. I think they fail the coherence test though. I hope they add something to the discussion process.

As with the previous case (i += i++) we have i being written to more than once without an intermediate sequence point. The pre-increment of i (++i) returns the current value of i plus 1 to be used in the evaluation of the expression and then guarantees to write it back to the i variable at some future time. The pre-incremented value could either be returned in a temporary object or in the i variable itself. This last option makes the implicit assumption that the compiler has a view on what constitutes the i variable and its value at all times.

From the compiler's viewpoint, the statement will be parsed and code produced. However, the effects of any code optimisation may change the outcome because of the side effects of some of the statement components.

The possible final values that I could imagine and how they could be produced are:

i+1

  1. i is pushed onto the stack.

  2. i is preincremented and the rvalue is pushed onto the stack.

  3. the two values are added and popped into the i variable.

  4. a sequence point happens and the value in step 2 is popped into i.

2i+1

  1. i is pushed onto the stack as a temporary object.

  2. i is preincremented and the rvalue is pushed onto the stack as a temporary object.

  3. the value in step 2 is popped into wherever the compiler thinks i is.

  4. the two values are added and popped into the i variable.

2i+2

  1. i is loaded into a register (Ri)

  2. i is loaded into another register (Rj) and incremented.

  3. Rj is copied into Ri.

  4. Rj is added to Ri.

The value 2i+2 is produced by the compilers I have tried (MS VC++5, Metroworks Codewarrior, Symantec Think C 5 and IBM xlc). There may be a difference in C++ is used. I am led to believe that if the pre-increment function is overloaded to have the form operator++(int) then a sequence point will occur because sequence points occur after the evaluation of a functions arguments. I am very hazy on this point having managed to avoid C++ and stay with C so far.

The above analyses assume that i is a standard type variable and not user defined.

In the final section of the previous article you made the comment that avoiding multiple writes in a single statement was a good guideline, but that the guideline may be ignored if the reasons for it are understood.

My question is:"What are the circumstances in which the guideline can be ignored?". My feeling is that something which relies on such a deep understanding of what is defined is probably something which will cause problems in the future. When someone making a change to the code makes a change which then invalidates the circumstances under which a double write is allowed the behaviour of the code may become undefined.

It is always a serious error to attempt to write twice to the same storage between sequence points however given:
int fn(int* i, int* j){ return ++(*i) + (*j)++;}
consider
int main(){
int i=0, j=0, k;
k = ++i + j++ ;  /* OK, three writes to different storage */
i = fn(&i, &j);  /* OK the two writes to i are protected by sequence points */
k = fn(&i, &i);  /* Undefined behaviour !! */
}
I am not advocating this style but if you understand when there is a risk of aliasing you can write to several variables between sequence points.

Notes: 

More fields may be available via dynamicdata ..