1

I am speaking in Standard, K&R C.

Given:

const char a[] = {1, 2, 3};
const char *p = NULL;

Are these two statements equivalent:

  1. *p = a;

  2. p = a;

Each of them would be on the third line of the snippet.

1 and 2 certainly don't look the same.

What's the difference between the two then?

1
  • Btw, it doesn't affect the answer, but there's no such thing as "Standard K&R C". K&R C, described in the first edition of "The C programming language", is now obsolete. Standard C comes in two main flavours, C89/C90 and C99. C89 is also called "ANSI C", because ANSI published in 1989, and then ISO published an effectively identical standard in 1990. C99 published in the other order - first ISO, then ANSI. The second and third editions of the K&R book relate to ANSI C, but I don't think that makes it "standard K&R C" Commented Aug 14, 2009 at 10:58

7 Answers 7

4

No.

p = a initializes the pointer to point to something else (usually it copies another pointer or you will point to a reference, ala p = &a.

*p = a initializes what p refers to. You are "dereferencing" (looking at) what p points to. If p points to NULL as in your example, you will crash (this is good! you do not want to accidentally access something and mess your program up).

In this case, p = a will point to the first of the array a[], and *p = a will attempt to change the first of the array (it won't work; you have it declared const).

Here is a small example program in C++, with almost identical syntax to C.

#include <iostream>

int main()
{
    char arr[5] { 'a', 'b', 'c' }; // arr[3] and arr[4] are set to 0
    char *ptr = arr; //point to 'a'

    for (int i = 0; i != 5; i++)
    {
       *ptr = 'f'; //this changes the array
       ptr++; //this changes what the pointer points to; moves it to next in array
    }

    for (int i = 0; i != 5; i++)
    {
        std::cout << *ptr << " ";
    }

    //outputs f f f f f
}
Sign up to request clarification or add additional context in comments.

1 Comment

"and *p = a will attempt to change the first of the array (it won't work; you have it declared const)." Slight correction: p points to NULL; a has the array. He's dereferencing NULL, as you said in your 2nd paragraph; not changing the array, as you said in the third one.
2

The * operator is what we call the dereference operator. To understand what it does, you must understand exactly what a pointer is.

When you do

char *p;

the "variable" p does not use the same amount of memory as a normal char, it uses more memory: it uses the amount of memory needed to correctly identify a memory position in your computer. So, let's say you use a 32-bit architecture, the variable p occupies 4 bytes (not the 1 byte you would expect from a char).

So, when you do

p = a;

you see clearly that you are changing the contents of the variable p, that is, you are putting another 32-bit number inside it: you are changing the address it is pointing to.

After that line executes, the value of p is the memory address of the character array a.

Now for the dereference operator. When you do

*p = 'Z';

you are telling the compiler that you want to store the value 'Z' ON THE ADDRESS pointed by p. So, the value of p remains the same after this line: it continues to point to the same address. It's the value of this address that has changed, and now contains 'Z'.

So, the final effect of

char a[] = {'a', 'b', 'c'};
char p = a;
*p = 'Z';

is the same as changing the first position of the array a to 'Z', that is:

char a[] = {'a', 'b', 'c'};
a[0] = 'Z';

NOTE: there is a difference when making a pointer point to an array: the variable that contains the array contains only the address of the first element, so a is the same as "the starting address of the array".

Usually you will see the & operator. It is an operator used to obtain the memory address of a variable. For example:

int number = 42;
int pointer = &number;
printf("%d", *pointer);

Here we have them all. The first line creates an integer variable and stores 42 inside it.

The second line creates a pointer to an integer, and stores the address of the variable number inside it.

The third line reades the value on the address pointed by the pointer.

So, the trick is to read *x as on the address pointed by x and &x as the address of x.

1 Comment

p = a is not a shortcut. It would confuse people more to init a pointer to an array like p = &a[0].
1

The first dereferences a null pointer, and tries to assign it the address of the array. This will be a compiler error, because char != char []. If it weren't, it would likely crash.

The second sets p to point to the the array.

Comments

1

I think you are mistaking:

char a[8];
char *p=a;

which is legal and does the same as:

char a[8];
char *p=NULL;
p=a;

with:

char a[8];
char *p=NULL;
*p=a;

which as others said would generate a compile error or a segmentation fault.

 In the left side of declarations you should read *x as pointer(x) while in
 statements it must be read as value_pointed_by(x). &x on the other hand
 would be pointer_to(x)

2 Comments

I tend to read the declaration char *p as "*p is a char", rather than "p is a char *", which in the early days helped keep things straight (and also helps in reading more complicated declarations). In retrospect it probably would have been clearer if the syntax was &char p to declare p a pointer to char.
Yes it would be better like that, with it being regarded as a different type. However, C being as it is, it is better to declare char p rather than char p, as the former won't apply to subsequent variables which makes it counterintuitive. char* p,q; is char* p; char q; instead of char *p,*q; which is what you could be lead to believe.
1

Here's a trick I used when I learned C (and still use today).

Whenever you see the * in front of a variable in your code, automatically read it as "what is pointed to by".

So you should be able to easily see that setting "p" to "a" is very different from setting "what is pointed to by p" to "a".

Also, since p is supposed to be pointing at a char, setting that char p is pointing at (currently the "char" at memory location 0 assuming null is 0) to a char pointer (a) is probably going to fail at compile time if you are lucky (depending on your compiler and lint settings it may actually succeed.)

from comment:In a function declaration like f(char c), I usually try to separate out the variable name from the rest of it--so it would be f( (char) c). so c is a char*. Exactly like a variable definition.

Also & usually reads as "The address of", but that gets even more iffy. A few examples of how I read things to myself. May or may not help you.

int a[] = {1,2,3}; // I mentally parse this as (int[]) a, so a is an int array.
int *p;            // p is a pointer to "integers"
int i;
p=a;               // p acts exactly as a does now. 

i=*p;          // i is "What is pointed to by" p (1)
i=p;           // i is some memory address
i=*a;          // i is what is pointed to by a (1)
i=p[1];        // Don't forget that * and [] syntax are generally interchangable.
i=a+1;         // Same as above (2).
p=&i;          // p is the address of i (it can because it's a pointer)
               // remember from hs algebra that = generally reads as "is", still works!
*p=7;          // what is pointed to by p (i) is 7;
a=*i;          // whoops, can't assign an array.  This is the only difference between
               // arrays and pointers that you will have to deal with often, so feel
               // free to use which ever one you are more comfortable with.

char c='a';
char *  d = &c;// d is a char pointer, and it is the address of c
char ** e ;    // e is a pointer to a memory location containing
               // a pointer to a char!
e=&d;          // gets d's address. a pointer to a pointer gets
               // the address of a pointer.  Messy but gets the job done

**e=5;         // what is pointed to by what is pointed to by e is 5.
*e=&'f';       // what is pointed to by e (which is a char * itself, and is still d!)
               // is set to the address of the memory location holding the value 'f'.
               // does not change c or e, just d! 

I haven't touched c in 10 years, so some of this may be a bit wrong, but it helps me to read it out loud that way.

2 Comments

What do you do when you see that in a function declaration?
I would suggest extending the way you read * to declarations too, so that int *p reads as "what is pointed to by p is an int", rather than "p is an int *" which is a bit nebulous.
0

No, they are not equivalent

If p = NULL, then doing *p = a will give you a segmentation fault.

Comments

0
  1. Because "*p" dereferences the pointer wouldnt this make "p" a "char**" ?
  2. This would point "p" to the first array as expected.

I guess they are not the same.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.