0

Say I have

  typedef struct exampleFooStruct foo; 
  typedef char* byte_ptr;

  struct exampleFooStruct{
     byte_ptr p;
     uint32_t num;
  }

  // ...

  foo* one =  malloc(sizeof(foo));
  one->p = 0x5;
  one->num = 0x4;

First of all, does one->p assign the value at one->p to be 0x5 or is it setting the address itself to 0x5?

I ultimately want to set the address itself to be 0x5, not the value at that address.

And if I want an int answer = 0x9, would I do

int answer = one->p + one->num;
//or
int answer = &(one->p) + one->num;
Gereon
  • 17,258
  • 4
  • 42
  • 73

3 Answers3

2
foo* one =  malloc(sizeof(foo));

This allocates space for a structure object of type foo and assigns its address to one. This is actually better written as:

foo *one = malloc(sizeof *one);`

By not repeating the type name, you avoid possible errors if the type of the pointer ever changes.

Note that at this point the value of one->p is garbage.

one->p = 0x5;

This is actually a constraint violation. Practically speaking, you should assume that it's illegal. one->p is a pointer, and 0x5 is a value of type int. There is no implicit conversion from integers to pointers (other than the special case of a null pointer constant, which doesn't apply here).

Your compiler should have at least warned you about this. In fact, any conforming C compiler is required to issue a diagnostic message. (It is, in my opinion, unfortunate that many compilers treat this as a warning rather than a fatal error by default, but there are historical reasons for that).

You could make it legal by doing a cast:

one->p = (byte_ptr)0x05;

That would store in the pointer object one->p the result of converting the integer value 5 to a pointer value.

Unless you're doing some kind of low-level embedded programming on a system where you know what's at that specific memory address, it almost certainly doesn't make sense to do that. 0x05, even after conversion, is unlikely to be a valid pointer value, and any attempt to use it is likely to crash your program -- if you're lucky. (If you're unlucky it will appear to "work".)

I ultimately want to set the address itself to be 0x5, not the value at that address.

If that's really what you want to do, then one->p = (byte_ptr)0x05; is the way to do it. Why do you want to do that? What is at location 0x05 in memory?

int answer = one->p + one->num;

one->p is a pointer, and one->num is an integer. You can add a pointer and an integer, but the result is a pointer, and you can't assign it to an int object without a cast. And with a cast, it very likely doesn't make sense.

If you want to store integer values, store them in integer objects.

(If you wanted to store 0x05 in the object that one->p points to, you'd first have to arrange for it to point to something, perhaps with another call to malloc. But that's not what you asked about, I won't go into that. Perhaps it's what you should have asked about, but I'd rather not make any assumptions.)

And if I want an int answer = 0x9, ...

Then you can write int answer = 0x9;. I assume that's not what you're looking for, but I can't tell just what that is.

Finally, what is it you're trying to accomplish? Could it be that you have an XY problem?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • It is a project on heap allocation. – Block o Butter May 06 '20 at 09:37
  • @BlockoButter That doesn't tell me why you want a pointer to memory address `0x05`. – Keith Thompson May 06 '20 at 17:21
  • I tried to pull a number out of thin air, which I learned confused everyone. 0x05 would be 0xF9284D21 or a variable, but out of abstraction, I just put 0x05. Learned my lesson, so next time I post a question, I'm going to try to simulate true form of things to give context to it. In true form, 0x05 would be a pointer to a heap and the integer num would be an offset number of some sort. – Block o Butter May 06 '20 at 23:55
1

oes one->p assign the value at one->p to be 0x5 or is it setting the address itself to 0x5

assuming byte_ptr is indeed a pointer (address), it will do what you probably expect and it will set the pointer to point to address 0x5

And if I want an int answer = 0x9, would I do you need to tell the compiler to treat the pointer as an integer. it will set answer to 0x9, but this program does not makes sense in my view.: int answer = (int)(one->p) + one->num;

nivpeled
  • 1,810
  • 5
  • 17
  • So I wouldn't need to use the & operation at all? If I do *(one->p), doesn't that return the value that p is pointing to, not the address itself (which is what I want.) – Block o Butter May 06 '20 at 09:10
  • probably not. I recommend you to read about pointers, deference and & operator. – nivpeled May 06 '20 at 09:11
  • Why don't you run your code, preferrably in a debugger? You'll be able to see the answers for yourself. – Gereon May 06 '20 at 09:13
  • @Inian the pointer itself was allocated as part of the malloc that allocated the whole "one" structure. – nivpeled May 06 '20 at 09:40
1

The root of all your problems is likely that you hide a pointer behind a typedef, which makes the code very confusing for everyone, including yourself. Please never do that.

First of all, does one->p assign the value at one->p to be 0x5 or is it setting the address itself to 0x5?

It generates a compiler message since the code isn't valid C. See "Pointer from integer/integer from pointer without a cast" issues.

I ultimately want to set the address itself to be 0x5, not the value at that address.

Then you need to cast: one->p = (byte_ptr)0x5;. But this is major code smell, even if the address 5 is valid for your system. Using char to access raw data is always wrong, to begin with, since it's a type with impl.defined signedness. And if you want to access physical memory directly, you almost certainly need to use a volatile qualifier.

if I want an int answer = 0x9, would I do

None of your alternatives. The first uses pointer arithmetic, the latter as well, but based on the address of the pointer itself. None make sense.

You'd do int answer = (uintptr_t)one->p + one->num;.


Overall, consider changing the code to this:

  typedef struct {
     uint8_t* p;
     uint32_t num;
  } foo;

  // ...

  foo* one =  malloc(sizeof *one);
  one->p = (volatile uint8_t*)0x5;
  one->num = 0x4;

  uint32_t answer = (uintptr_t)one->p + one->num;
Lundin
  • 195,001
  • 40
  • 254
  • 396