1

In the strchr reference at http://www.cplusplus.com/reference/cstring/strchr/, this example is provided.

/* strchr example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[] = "This is a sample string";
  char * pch;
  printf ("Looking for the 's' character in \"%s\"...\n",str);
  pch=strchr(str,'s');
  while (pch!=NULL)
  {
    printf ("found at %d\n",pch-str+1);
    pch=strchr(pch+1,'s');
  }
  return 0;
}

Why does subtracting the char array str from the char pointer pch plus one give an int? (as denoted by the %d format type) If I remove "-str", the program wouldn't execute until I change %d to %s.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
freesushi
  • 69
  • 7
  • 3
    Arrays decay to pointers when used in an expression and difference of pointers is distance (number of elements) between them. – zch Jan 03 '15 at 16:35
  • @zch: Good thing you cleared up OPs confusion about array semantics. Still, what about his question? – Deduplicator Jan 03 '15 at 16:46

3 Answers3

4

The short of it is, that's a bug:
That expression might be of type int, or you might have Undefined Behavior in the call to printf.

Let's take it step by step:

  1. You are not actually subtracting an array from a pointer, but a pointer from a pointer:
    In nearly all contexts, an array decays to a pointer to its first element.

  2. What type is the difference of two pointers (which is only defined if they point at or directly behind elements from the same array)?

    ptrdiff_t (That's what that typedef in <stddef.h> is for.)

  3. ptrdiff_t might happen to be int, but don't depend on it.
    Instead, use the proper format-specifier: %ti.

Community
  • 1
  • 1
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • 1
    May be, it was the better decision to answer it (+1) – πάντα ῥεῖ Jan 03 '15 at 16:57
  • Just curious: What's that "an array *name* decays" stuff? (instead of just "an array decays") I've seen this here quite often. – mafso Jan 03 '15 at 18:37
  • @mafso Edited in an appropriate link for more explanation. – πάντα ῥεῖ Jan 03 '15 at 18:46
  • @πάνταῥεῖ, I know what array decay is. My point was, that it's always "an array **name** decays" on SO. While this is correct, it seems to imply that arrays not denoted by the "array name" wouldn't decay, which isn't true. So what's the point of always emphasizing the "name" which seems, to me, totally unrelated here? Thinking about it, this could be C89 legacy; if `f().a` is an array, in C89 it doesn't decay. But if `p` has type `int (*)[]`, `*p` also decays in C89, so even there I don't fully understand it. – mafso Jan 03 '15 at 20:03
  • @mafso The link doesn't hurt though, does it? – πάντα ῥεῖ Jan 03 '15 at 20:07
  • @πάνταῥεῖ, sure, I don't disagree with the edit. It just doesn't answer my question (which addressed Deduplicator anyway). It's virtually always "an array name decays" on SO, and I wanted to know the reason for that. To me, this sounds like "an array with five elements decays", which is also true, but somewhat implies arrays with other number of elements wouldn't decay. – mafso Jan 03 '15 at 20:23
  • @mafso _"and I wanted to know the reason for that"_ It's immanently behaving like this, and may be for compatibility with c. There's not really a point, asking for _the reason_. – πάντα ῥεῖ Jan 03 '15 at 20:36
  • @πάνταῥεῖ, I'm not asking why something in C or C++ is the way it is. I'm asking why it is always described in the unnecessarily restricted way it is on SO, which almost always reads "an array ***NAME*** decays" instead of the simpler and more complete "an array decays". Expressions of array type decay (in C99) independent of whether they are "array names" (identifiers denoting an array) or not. They decay if not operand of `sizeof` or `&`, no matter if they are an identifier or some other expression being of array type. – mafso Jan 03 '15 at 21:03
  • @mafso You don't actually have to go to C99 to find an example of a nameless array decaying: think string-literals. So, yes, strictly speaking it should be "an array decays", however it is designated. – Deduplicator Jan 03 '15 at 21:53
0

Array names decays to pointers (in most cases) to its first element. Subtraction of two pointers yields an data of ptrdiff_t type, provided both points to elements of the same array.

haccks
  • 104,019
  • 25
  • 176
  • 264
-2

You are looking at one of the oddities of C/C++ and pointers. Pointer and array syntax and semantics are simply nuts.

str is a pointer to a char (as well as an array). pch is a pointer to a char as well.

If you subtract two pointers to the same type you get the number of elements between them.

You can even do

    3 [str] ;

which is equivalent to

   str[3] ;

and is equivalent to

   *(str+3) ;

Your expression:

  pch - 1

has the type pointer to char. Your expression

  pch - str

has the type int.

user3344003
  • 20,574
  • 3
  • 26
  • 62
  • Nothing of your post in any way touches on OPs question, which was about the **type** of the difference. Also, pointers and arrays are fundamentally different thing, and conflating them is a rife source of bugs and frustration, even though (or probably more because) there's array decay. – Deduplicator Jan 04 '15 at 15:07