-1

Im new to C programming and I'd like to know how does a pointer constant differ from a constant variable in this case:

#include <stdio.h> 
int main(void) 
{ 
   int cnt = 0;        

   char val; 
   char mystr[20] = “hello there!”; 
   char *p_str2, str2[20] = “zzzzzzzzzzzzzzzz”; 
   char* p_mystr = mystr; 

   p_str2 = str2; 

   while (*p_mystr != 0x00)
   {
       val=*p_mystr++; 
       cnt++; 
   } 

   return 0; 
} 

also, how does mystr differ from mystr[2] (what data type is each variable) and is there anything wrong with p_mystr = mystr[2]; could this be written better (ie: why is *p_mystr= mystr[2]; correct)?

akaHuman
  • 1,332
  • 1
  • 14
  • 33
user10975
  • 11
  • 2
  • 5
    You strongly need [this](http://www.c-faq.com/aryptr/index.html)! – haccks Mar 06 '14 at 15:50
  • Also consider http://stackoverflow.com/questions/1641957/is-array-name-a-pointer-in-c – n0p Mar 06 '14 at 15:55
  • There is no "pointer constant" or "constant variable" here, so your first question is unclear. – interjay Mar 06 '14 at 15:56
  • The only constants in that example are your string literals (and possibly the integer literals as well, depending on your platform)... Also, consider that a pointer is usually stored in a "variable" (although variables obviously aren't always pointers)... – twalberg Mar 06 '14 at 16:01

3 Answers3

0

Both your variables mystr and str2 are character arrays stored on the stack. There's nothing "constant" here, except the string literals used to initialize your character arrays.


p_mystr is a pointer, mystr[2] is a character. Where is your *p_mystr= mystr[2]; supposed to be? It better not be before p_mystr's initialization to a valid address.

Medinoc
  • 6,577
  • 20
  • 42
0

You just asked a mouthful!

  1. A pointer is a very different type to a simple data type (a char * compared to a char). A char just has a single value e.g. 'a'. You can think of a pointer as a memory address - it means, go to the memory address 0x0123F1A and treat what you find there as a char. Pointers can be tricky to get your head around so it's worth reading up on e.g. here
  2. mystr is an array of characters. In some ways it will behave like a pointer to the first item in the array, but it is genuinely a distinct type. mystr[2] has type char - it is the char found at index 2 in the array (i.e. the third char since array indices start at 0).
  3. There is nothing wrong with p_mystr = mystr - it is safe to assign from a char-array to a char-pointer, and the meaning is to make the pointer point to the first item in the array.
  4. *p_mystr=mystr[2] means something else. The * operator means "the value pointed to", so what this means is "in the memory address where p_mystr is pointing, copy the character mystr[2]"
Graham Griffiths
  • 2,196
  • 1
  • 12
  • 15
0

Except when it is the operand of the sizeof or unary & operators, an expression of type "N-element array of T" will be converted to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. The result is not an lvalue, meaning it cannot be the target of an assignment.

So, given the declaration

char mystr[20] = "hello there!";

the following are all true:

  Expression        Type            Decays to      Result
  ----------        ----            ---------      ------
       mystr        char [20]       char *         address of mystr[0]
      &mystr        char (*)[20]    n/a            address of mystr
      *mystr        char            n/a            value of mystr[0], or 'h'
    mystr[i]        char            n/a            i'th character
   &mystr[i]        char *          n/a            address of mystr[i]
sizeof mystr        size_t          n/a            20 (number of bytes in array)

The address of the array is the same as the address of the first element of the array (no storage is set aside for a mystr variable separate from the array elements themselves), so the expressions mystr, &mystr and &mystr[0] all return the same value, but the types of the expressions are different; mystr and &mystr[0] both have type char *, but &mystr has type char (*)[20], or "pointer to 20-element array of char".

The results for str2 are the same.

Given the declaration

char *p_mystr;

we get the following

    Expression      Type        Result
    ----------      ----        ------
       p_mystr      char *      value in p_mystr
      *p_mystr      char        value of character pointed to by p_mystr
      &p_mystr      char **     address of p_mystr variable
sizeof p_mystr      size_t      number of bytes in pointer value

The table for p_str2 is the same.

Now it's a matter of matching up types. p_mystr = mystr works because both expressions have type char *; p_mystr winds up pointing to mystr[0]. Similarly, *p_mystr = mystr[2] works1 because both expressions have type char. Same for val = *p_mystr++, although note in this case that *p_mystr++ is parsed as *(p_mystr++); the increment will be applied to the pointer value, not the character value.

Note that an expression like p_mystr = &mystr; should get you a diagnostic to the effect that the types don't match.

Your question title mentions const pointers and variables, although that doesn't appear in the question body. Basically, for any type T:

T *p0;                 // p0 is a non-const pointer to non-const T
const T *p1;           // p1 is a non-const pointer to const T
T const *p2;           // p2 is a non-const pointer to const T
T * const p3;          // p3 is a const pointer to non-const T
const T * const p4;    // p4 is a const pointer to const t
T const * const p5;    // p5 is a const pointer to const t

Which breaks down as:

  • You can write to p0 (change it to point to something else) and *p0 (change the thing being pointed to);
  • You can write to p1 and p2 (change them to point to something else), but you cannot write to *p1 or *p2 (cannot change the thing being pointed to);
  • You cannot write to p3 (cannot change it to point to something else), but you can write to *p3 (change the thing being pointed to);
  • You cannot write to p4 or p5 (cannot change them to point to something else), nor can you write to *p4 or *p5 (cannot change the thing being pointed to).

So, if you declared something like

const char *cptr = mystr;

you could not modify the contents of mystr through the cptr variable, even though mystr is not declared const itself.

Note that trying to go the other way, such as

const int foo = 5;
int *fptr = (int *) &foo;
*fptr = 6;

invokes undefined behavior; it may or may not work, depending on the implementation (the language definition allows implementations to put const-qualified objects in read-only memory).


1. If p_mystr is pointing somewhere valid, that is.
John Bode
  • 119,563
  • 19
  • 122
  • 198