pointer array subtraction problem

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

pointer array subtraction problem

2,650 次查看
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,328 次查看
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,328 次查看
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,328 次查看
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,328 次查看
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 项奖励
回复