pointer array subtraction problem

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

pointer array subtraction problem

2,783件の閲覧回数
Pyriform
Contributor I

Hi,

 

I am using CodeWarrior with a MC9S08QE128 and have found a curious probelm when trying to subtract elements of arrays when they are pointers.  Here is a sample of code which reproduces the problem:

 

 

const char *const ordinals[]={  "first", "second", "third"};void main(void) {  const char *o1p;  const char *o2p;  int o1len;  // I would expect this to assign to o1len the length of the string pointed  // to by ordinals[0]  o1len=ordinals[1]-ordinals[0];    // This really does assign to o1len the length of the string pointed to by  // ordinals[0]  o1p=ordinals[0];  o2p=ordinals[1];  o1len=o2p-o1p;

...

}

 


   The first subtraction actually assignes a value of 2 to o1len, presumably because it is subtracting the addresses of the elements, rather than their actual pointer values.  Here is the listing produced:

 

ANSI-C/cC++ Compiler for HC08 V-5.0.24 Build 7134, May 15 2007    1:  #include <hidef.h> /* for EnableInterrupts macro */    2:  #include "derivative.h" /* include peripheral declarations */    3:      4:  const char *const ordinals[]=    5:  {    6:    "first", "second", "third"    7:  };    8:      9:  void main(void)    10:  {Function: main

...

  0000 a7fa     [2]             AIS   #-6   11:    const char *o1p;   12:    const char *o2p;   13:    int o1len;   14:     15:    // I would expect this to assign to o1len the length of the string pointed   16:    // to by ordinals[0]   17:    o1len=ordinals[1]-ordinals[0];  0002 ae02     [2]             LDX   #2  0004 8c       [1]             CLRH    0005 9eff05   [5]             STHX  5,SP   18:       19:    // This really does assign to o1len the length of the string pointed to by   20:    // ordinals[0]   21:    o1p=ordinals[0];  0008 320000   [5]             LDHX  ordinals  000b 9eff01   [5]             STHX  1,SP   22:    o2p=ordinals[1];  000e 320002   [5]             LDHX  ordinals:2  0011 9eff03   [5]             STHX  3,SP   23:    o1len=o2p-o1p;  0014 95       [2]             TSX     0015 e603     [3]             LDA   3,X  0017 e001     [3]             SUB   1,X  0019 87       [2]             PSHA    001a e602     [3]             LDA   2,X  001c f2       [3]             SBC   ,X  001d 87       [2]             PSHA    001e 8a       [3]             PULH    001f 88       [3]             PULX    0020 9eff05   [5]             STHX  5,SP   24:       25: 

 

 The second subtract does what I expected, so I have a solution to this problem, but I do not understand what is wrong with the first case.  Am I doing something silly, or is it a compiler bug?

 

Thanks,

 

David.

ラベル(1)
タグ(1)
0 件の賞賛
返信
4 返答(返信)

1,461件の閲覧回数
pgo
Senior Contributor V

Dear Pyriform,

 

As you suggest, this does look like a compiler bug to me - or at least an unintentional operation. 

 

Using

o1len=(int)ordinals[1]-(int)ordinals[0];

 

produces the expected value.

 

However I believe that pointer arithmetic is only guaranteed to be sensible for pointers into the same object (and one element beyond for arrays).  So perhaps this isn't really a bug since the operation you are doing is, strictly speaking, undefined in C.  In practice I would also expect it to work as you expected.  It is certainly not portable code.

 

bye

Message Edited by pgo on 2009-07-02 10:47 AM
0 件の賞賛
返信

1,461件の閲覧回数
Pyriform
Contributor I
Thanks for that.  I was aware that it wasn't really the right way of doing things, but thought it would be considerabbly more efficient than a strlen() call.  I am surprised that the compiler didn't give me a warning, though (especially given some of the things it does warn me about).
0 件の賞賛
返信

1,461件の閲覧回数
Lundin
Senior Contributor IV
First of all, look at the declaration. You have declared an array of constant pointers to various constant strings. You have also declared 3 independent constant strings (arrays). You have not declared an array of strings.

Be aware of that you have allocated 3*sizeof(const char* const) + sizeof("first") + sizeof("second") + sizeof("third") bytes.

So the three pointers point at 3 different arrays. These arrays may be allocated at entirely different places in the constant memory, as they are declared independantly, and not as a 2D array.

As stated earlier, you cannot do pointer subtractions on pointers pointing at different arrays: this is undefined behavior in C, and it is the responsibility of the programmer to check for this.

Had you declared a 2D array, the code would work as you expected (though this might be less effective memory-wise):

const char ordinals[][7]=
{
"first", "second", "third"
};

o1len=ordinals[1]-ordinals[0]; /* will give result 7 */


I suspect your problems stem from confusion about the difference of pointers and arrays in C. Here is some good reading on the subject: http://c-faq.com/aryptr/index.html
0 件の賞賛
返信

1,461件の閲覧回数
CompilerGuru
NXP Employee
NXP Employee

I filed a (internal) bugreport on the initial code snippet. The code is indeed "undefined behavior", but the code the compiler generates is not ok regardless.

 

Daniel

0 件の賞賛
返信