-4
#include <stdio.h>

int main(void)
{
    int a = 3;
    int* p;
    
    //p = &a;
    *p = a;
    printf("%d", *p);
    
    return 0;
}

error code: Segmentation fault (core dumped)

Q1. I know that pointers output the values of operands. Why is p = &a; and *p = a different?

Q2. When int* p = &a; is declared, does p = &a, not *p = &a?

dbush
  • 205,898
  • 23
  • 218
  • 273
SUJI
  • 7
  • 2
  • 3
    While these aren't bad questions, they are answered by a [good reference book](https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list). – tadman Jun 16 '23 at 14:34
  • `int* p` is an *uninitialized* pointer, and `*p = a` exercises it. **Undefined behaviour**. `p = &a` initializes it properly. – tadman Jun 16 '23 at 14:34
  • To me, this question basically says "I have no idea what pointers are or how to use them, and although I know there's a wealth of documentation that explains them in detail, I'm hoping that asking questions about buggy examples will be a shortcut to learning about them." It won't. Spend your time reading a tutorial that covers pointers and arrays. – Tom Karzes Jun 16 '23 at 16:03

2 Answers2

3

I know that pointers output the values of operands. Then isn't p = &a; not also *p = a;?

Pointers don't "output" anything. They store addresses. As for the difference, this:

p = &a;

Takes the address of a and assigns it to p, while this:

*p = a;

Takes the value of a and assigns it to whatever p points to. In the above, the dereference operator * basically means "get whatever this pointer points to".

This also means that if p isn't set to point anywhere, you trigger undefined behavior due to dereferencing an uninitialized pointer. In this particular case your code crashed as a result (probably due to attempting to access an invalid memory address), but there is no guarantee this will happen.

When int* p = &a; is declared, does p = &a, not *p = &a?

The above declares p to have type int *, and initializes it to the address of a. In this case * is not the dereference operator, but part of the type declaration of p.

dbush
  • 205,898
  • 23
  • 218
  • 273
1

Why is p = &a; and *p = a different?

p = &a stores the address of a into p.

*p = a stores the value of a into the thing p points to.

After writing p = &a, the following conditions are true:

 p == &a; // int * == int *
*p ==  a; // int   == int

and the statement

*p = 5;

is exactly equivalent to writing

a = 5;

The expression *p basically acts as an alias for the variable a.

In your code, the line

*p = a;

gave you a segfault because p had not yet been assigned to point to a writable location. Unless explicitly initialized, the contents of a local variable1 are indeterminate — it could be anything.

When int* p = &a; is declared, does p = &a, not *p = &a?

In a declaration the * is only there to indicate type; it does not dereference p, any more than int a[N]; indexes into a or void f(void) calls f. So the declaration initializes p with the result of the expression &a (which has type int *).

Declarations in C are composed of two main sections — a sequence of declaration specifiers followed by a comma-separated list of declarators.

Declaration specifiers include type specifiers (int, char, float), type qualifiers (const, volatile), storage class specifiers (auto, static, register), and a few others.

Declarators contain the name of the thing being declared, along with information about that thing's array-ness, function-ness, and/or pointer-ness. In the declaration

unsigned long a[N], *p, f(void);

the declaration specifiers are unsigned long and the declarators are a[N], *p, and f(void). The types of a, p, and f are specified by the combinations of the declaration specifiers and declarators, so the type of a is "N-element array of unsigned long, the type of p is "pointer to unsigned long", and the type of f is "function taking no parameters and returning unsigned long".

Remember that in a declaration the * operator is always bound to the declarator, not the type specifier. The declaration

T* p; // for any type T

is always parsed as

T (*p);

meaning if you write a declaration like

T* p, q;

only p will be declared as a pointer; q will be declared as a regular T. If both need to be declared as pointers, you'd write

T *p, *q;

  1. Strictly speaking, we mean something with auto storage duration; declared within a block without the static keyword.
John Bode
  • 119,563
  • 19
  • 122
  • 198