In C, why can't you declare a pointer and point it directly to a number, without malloc?

In C, why do X and Y work but not Z?

//X     
int num = 5;
int *ptr;
ptr = #

//Y
int *mptr = (int *)malloc(sizeof(int *));       
*mptr = 5;       

//Z
int* myptr;
*myptr = 5;

      

In Z, I declare a pointer and try to point it to a number, but I get a segmentation error. But it seems to me that I am doing the same thing in Z as X and Y. In X I just use the variable num instead of the number 5 directly, and in Y I just use the heap to store the variables instead of the stack. So why does X and Y work but Z doesn't?

+4


source to share


11 replies


//X     
int num = 5;
int *ptr;
ptr = #

      

For the above, the int value "num" is assigned to the stack or in the program data segment, so it has an address. Let's pretend it was assigned by the compiler at 0x12345678. You are creating int * ptr. This address also has an address of 0x20000000. The address currently points to random data. We want the pointer to 0x20000000 to point to the data value at 0x12345678 so that we can read the contents of 0x12345678 and return the value 5 ... so we place 0x12345678 inside the store at 0x20000000 (we set ptr = &. Num)

//Z
int* myptr;
*myptr = 5;

      



For the second example, we only have 0x20000000 (myptr). Its a pointer and it currently points to nowhere and nowhere. When we do * myptr = 5, we are looking at the address stored at 0x20000000. Its random, so it might be 0xffff0000 lets use this example. Then it will try to write the value 5 to that address (0xffff0000), which does not exist and causes a segfault.

So, in your last example, the pointer exists, but it doesn't point anywhere invalid, so when you try to write where it points, you either corrupt the valid memory or cause a segment error.

+4


source


You have not specified what it points to myptr

. You only declared it as a pointer (i.e. a Variable used to point somewhere), but you haven't initialized it. In X and Y, you are actually initializing pointers:

//X     
int num = 5;
int *ptr;       /* Declaration */
ptr = #     /* Initialization */

//Y
int *mptr = (int *)malloc(sizeof(int));   /* Declaration + Initialization*/ 
*mptr = 5;      /* De-referencing*/ 

//Z
int* myptr;  /* Declaration only */
*myptr = 5;  /* De-referencing before initialization */

      

The Z is the only ads: int* myptr

. You are trying to remove the reference to the pointer on the next line, i.e. *myptr = 5;

... This results in a seg error because it myptr

hasn't been initialized yet.



Edit

Note that, as David Holzer pointed out, when you call malloc you probably wanted to write malloc(sizeof(int))

, not malloc(sizeof(int*))

.

+2


source


Pointers must point to memory locations. (Unless, of course, the pointer is null or invalid, but in that case, you still can't spell it.)

The expression 5

does not indicate a memory location. There is no memory 5

for waiting. We say which 5

is a value (or sometimes an r-value) for this reason.

Expressions specifying memory locations are called l values. (You may think I was behind the place). If you want to specify the containing location, 5

you will need to add code that reserves the memory area. This code will use the l value to reference this memory location. To be clear, the term l-value means an expression, not a memory location.

In your code:

  • X: int num = 5;

    Reserves the location, names it, num

    and stores 5

    in it. L value num

    .
  • Y: malloc(sizeof(int)

    (sic) reserves the location and *mptr = 5;

    stores the value in it. L value *mptr

    .
  • Z: *myptr

    is an l-value, however it doesn't denote a memory location because you haven't pointed myptr

    to any memory. So this code compiles, but it invokes undefined behavior: the value of l must indicate a valid memory location at the point at which it is evaluated.

NB. The l values ​​and r values ​​are usually poorly explained by tutorials, so be careful when searching the web. (I couldn't find good pages that were only C).

+2


source


Pointers are variables for storing memory addresses of other spaces. When a pointer is declared, it has no memory, it must be explicitly initialized by assigning it to some already existing variable or allocating memory using the C library malloc()

function.

In your case, X, ptr is made to point to an address num

, and hence it reflects the num value once defined.

Likewise in the case of Y, memory is explicitly allocated and a pointer mptr

is made to point to it using

int *mptr = (int *)malloc(sizeof(int *)); 

      

But in the case of Z, the pointer has just been declared, but it is not assigned or allocated in any memory location. Thus, the pointer points to some "wild" place that is outside the scope of the executable program, and therefore, ultimately throws a segmentation fault, which usually means out of memory access.

+1


source


You must assign a value to a variable before using that value. In Z, you use the value myptr

before you assign it. Neither of your two other examples do this.

//X     
int num = 5; // Assign num a value
int *ptr;
ptr = # // Assign ptr a value

//Y
int *mptr = (int *)malloc(sizeof(int *));     // Assign mptr a value
*mptr = 5;       // Use the value

//Z
int* myptr; // Doesn't assign myptr a value
*myptr = 5; // Uses myptr value

      

0


source


int num = 5; // name a memory location "num" and store 5 in it
int *ptr;    // name a memory location "ptr"
ptr = #  // store address of "num" in "ptr"

//Y
int *mptr = (int *)malloc(sizeof(int *)); // name a memory location mptr
// then (wrongly, should have been sizeof(int)) allocate enough memory to store
// a pointer and store the address of that allocated memory in "mptr"
*mptr = 5;  // write value 5 in that anonymous memory location allocated by malloc
// that mptr is pointing at

//Z
int* myptr; // name a memory location "myptr", don't write anything to it
*myptr = 5; // try to write value of 5 into memory pointed by myptr -- 
//except myptr is not pointed anywhere yet, get undefined behavior

      

0


source


What stops you is not necessarily the C language, but your operating system.

  • In the case of X, your memory requirements can be inferred from your code, and memory is allocated before your program is executed.
  • In case Y, you are requesting a dynamic memory allocation and the operating system tries to fulfill that request.
  • In case Z, the memory requirements cannot be inferred from code, and there is no request made to the operating system to dynamically allocate memory; thus, no memory was allocated: you get a segmentation fault when trying to dishonor unallocated memory.

A segmentation fault is reported by the operating system to protect you from dereferencing unallocated memory; is a security feature in modern operating systems designed to prevent the use of your program from crashing data elsewhere on the system.

In the case of Z, your pointer might be set to a random address. If you grab this address and store it 5

in this location, you can overwrite other program data in memory.

Imagine the chaos that would arise from programs interfering with each other's data in memory: you can no longer trust your variables because another program could work with them, or even worse - a small error in your program could overwrite your operating system in memory and crash your entire car; therefore the modern operating system prevents you from doing this.

If you've been programming in bare metal (i.e. no operating system), you could honor all the random memory addresses you want as there won't be anything around so you don't shoot in the foot.

0


source


In fact, syntactically speaking, you can do this using an explicit cast:

//Z
int* myptr;
myptr = (void *)5;

      

So it can be (dangerous) used as an int, but if you try to dereference it, you run into a segmentation fault as the point myptr at address 0x5 is invalid .

0


source


  • Pointers are called "pointers" for a specific reason. Data pointers can only point to lvalues, that is, objects that have a place in storage (in memory).

    The "number" has no place in memory. "Number" is not an lvalue. It is impossible to point out what is not the case.

  • Your example labeled Z is not even remotely like trying to point to a pointer to a number. Your examples labeled X and Y clearly show that in order to make the pointer a ptr

    point somewhere, you must assign a value directly ptr

    , not *ptr

    . In example Z, you never assign a value myptr

    .

0


source


Your bad code

//Z
int* myptr;
*myptr = 5;

      

does the following (assuming 32-bit addresses and 32-bit int

):

  • int* myptr;

    declare myptr

    as pointer to int. This means that it contains an address int

    . Since you haven't initialized myptr

    , myptr

    contains an undefined value. It can be the absolute address 0x00000000 or some seemingly random value (bits from the fact that the last took this place in memory, most likely).

  • *myptr = 5;

    is an instruction to store an integer value 5

    (0x00000005) in 4 contiguous bytes of memory located at an address contained in myptr

    . Whether or not you can write to that location in memory depends entirely on what that address is . If you're lucky, your program will be at fault and die. If you're out of luck, it will trick your memory into something that matters (like the communication of your call stack or something worse).

Then your program will run fine ... until it crashes in strange and mysterious ways. And you're going to rip your hair out trying to figure out what's going on. Don't ask me how I know this.

Now you can say something like

myptr = 5 ;

      

which does something different: it assigns the myptr

absolute address 0x00000005. Then if you say something like:

*myptr = 3*5 ;

      

It will try to store the integer value 15 (0x0000000F) in 4 bytes located at the absolute address 0x00000005. It will still (almost certainly) crash, but at least it will do it consistently and reproducibly.

For an argument, my addresses in address assume a 32-bit address space.

0


source


You cannot do this, as in this declaration Z is only a pointer and does not contain any memory. you need to "point" to Z to new memory

you can do it in three ways:

int* myptr;
myptr(int *)malloc(sizeof(int));

myptr = 5;

      

OR

int* myptr = new int;

      

OR

int A;
int* myptr = A;

      

-1


source







All Articles