0

I m running this using rextester (online compiler). I followed a tutorial but there is something I don't understand.

I thought it would be better to write my question directly inside the code.

//gcc 5.4.0

#include <stdint.h>
#include  <stdio.h>

uint8_t var1 = 17;
uint8_t var2 = 23;
uint8_t arr[] ={7,9,11};

uint64_t *ptr1;//pointer
uint64_t *ptr2;
uint64_t *ptr3;

int main(void)
{

    printf("var1: %d\n", var1) ;

    //connecting pointer to address
    ptr1 = &var1;
    printf("address of ptr1: %d\n", ptr1) ;
    printf("value of ptr1: %d\n\n", *ptr1) ;

    //connecting pointer to address + 1
    ptr2 = &var1 +1;
    printf("address of ptr2: %d\n", ptr2) ;

    //assign value to pointer
    *ptr2 = var2;
    printf("value of ptr2: %d\n\n", *ptr2) ;

    //try on array
    ptr3= &arr;//no need to point element 0, or yes? 
    printf("address of ptr3: %d\n", ptr3) ;
    printf("value of ptr3: %d\n\n", *ptr3) ;//i expect 7
    return 0;
}

Any help would be very appreciate to help me understand the right behaviour of pointers in c and cpp I made a lot of tries but i m not able to link a pointer to an array

Edit after response of mato:

Do you think this is a clean way to work with pointer and array? Or there are better solution which take care of not overwriting memory?

//gcc 5.4.0

#include <stdint.h>
#include  <stdio.h>

uint16_t var = 17;
uint16_t arr[] ={3,5,7,11,13};
uint16_t *ptr;

int main(void)
{

printf("var: %d\n", var) ;

//connecting pointer to address
ptr = &var;
printf("address of ptr: %d\n", ptr) ;
printf("value of ptr: %d\n\n", *ptr) ;

//try on array
for (uint16_t n =0;n<5;n++){
ptr= &arr[n] ;
printf("item: %d value: %d ads: %d pointer: %d\n", n, arr[n], ptr, *ptr) ;
}
return 0;
}
aster94
  • 329
  • 1
  • 3
  • 13
  • An array name is a pointer to its first element. (element[0]). So you can assign an array name to a pointer but of the same type. – Raindrop7 Oct 02 '17 at 22:39
  • `*ptr2 = var2` introduces undefined behavior in your program because, in this instance, `ptr2 = &var + 1` is **not** a valid way to get the address of anything. The compiler isn't guaranteed to order variables in any specific way in memory. Undefined behavior can cause your entire program (even parts that look unrelated to the one that introduced the undefined behavior) to act unpredictably. – zneak Oct 02 '17 at 22:41
  • You cannot print uint8_t with %d format. Try `printf("...%d...", (int)x);` – user31264 Oct 02 '17 at 22:43
  • 1
    @user31264, you absolutely can. The C standard specifies that integral arguments smaller than an `int` are promoted to `int` in variadic argument calls. – zneak Oct 02 '17 at 22:44
  • Related to this question: https://stackoverflow.com/a/30194696/251153 – zneak Oct 02 '17 at 22:45
  • @Raindrop7 i changed all the times to uint32_t and it worked, i didn t thought about what you said but know it is clear and logic. could you copy and paste your comment as answer? – aster94 Oct 02 '17 at 22:53
  • Zneak thanks for pointing this out, i m still experimenting, now i know i shouldn t do this kind of operations – aster94 Oct 02 '17 at 22:56
  • `printf("address of ptr1: %d\n", ptr1) ;` is not correct description. This is *value of `ptr1`, or *address of `var1`*. The address of ptr1 would be `&ptr1`. It sounds like you are still mixing up *a pointer* with *a thing the pointer is pointing to*. The value of a pointer is the address of the thing it is pointing to. – M.M Oct 03 '17 at 00:16

2 Answers2

2

You are doing many mistakes. Up to the point, that g++ does not compile the code and explains why pretty good.

Pointer is an address. There is no "connecting pointer to address". ptr1 = &var1; means literally "store address of var1 in variable named ptr1"

You use incompatible pointer types. So as long as you dereference it (e.g. using *) you are going into undefined behaviour.

I am pretty sure you can reinterpret any type of data as char* or unsigned char*, I image this is true for equivalent types like uint8_t, i.e. single byte types.

You, however, are going the other way, you declare 1-byte data, and are pretending it's a 4 byte int. Basically you force the program to read memory out the variable bounds.

Fact, that *ptr1 and *ptr2 give result you expect is a rather lucky coincidence. Probably memory behind them was zeroed. For ptr3 it isn't because you have filled it with other element of the array (7 and 9).

I believe you also use wrong type specifier for printing. %d is for int, uint8_t should be described as hhu and uint64_t as lu. I am not 100% convinced how fatal this is, because of platform specific widths and integer promotions.

You should use matching types for your pointers and variables.

luk32
  • 15,812
  • 38
  • 62
2

It seems that you do understand what pointers are and you can use them with basic types.

There are two problems in your code. First is this part:

//connecting pointer to address + 1
ptr2 = &var1 + 1;

Here you assigned some address to variable ptr2. Up to this point there is nothing dangerous about that.

But then you assign a value to memory at that address

//assign value to pointer
*ptr2 = var2;

This is dangerous because you, as a developer, don't know what is stored at that address. Even if you are lucky right now, and that part of memory isn't being used for anything else, it will most likely change once your program gets longer and then you will have hard time searching for the bug.

Now arrays usually are a bit confusing, because when you create an array like this:

uint8_t arr[] = {7,9,11};

three things happen.

  1. Your program allocates continual block of memory, that fits 3 variables of type uint8_t. The 3 variables in this context are called elements.
  2. The elements will get the provided initial values 7, 9 and 11.
  3. An address of first element (the one that contains value 7) will be stored in arr.

So arr is actually of type uint8_t *.

In order to get the last part do what you expect, you just need to change this one line (remove the &):

ptr3 = arr;

EDIT: BTW watch and understand this course and you will be expert on C memory manipulation. Video is a bit dated, but trust me, the guy is great.

EDIT2: I just realised the other answer is absolutely correct, you really need to match the types.

mato
  • 173
  • 8
  • I will watch the course very soon thank you very much! Meanwhile if you can see my updated question – aster94 Oct 02 '17 at 23:26
  • You only address places in memory that you know, what they are. So yes, pretty safe. One detail: use %p for printing pointers instead of %d – mato Oct 02 '17 at 23:50