0
long double i, *ptr;
ptr = &i;

I want to modify the value of byte No. 4. Size of long double is 8 byte. So is it possible by subtracting 4 from *ptr ? i.e

(ptr)-4 = 9;
Darshan Rivka Whittle
  • 32,989
  • 7
  • 91
  • 109
TPSstar
  • 121
  • 1
  • 13
  • 1
    You have to use bit operators to extract the bytes, modify the one(s) you want to modify, and recombine them. This applies whether you're using a pointer or not. By the way normally when people want to this kind of byte extraction/modification/recombination thing they're dealing with integers. Are you sure you want `i` to be a floating point variable? – Aaron Golden Apr 25 '13 at 18:07
  • http://stackoverflow.com/questions/4439078/how-do-you-set-only-certain-bits-of-a-byte-in-c-without-affecting-the-rest – Anil Vaitla Apr 25 '13 at 18:11
  • actually im new to the pointers concept, the above code might be wrong . i think im de-referencing the ptr above.. what ptr-4 will does? – TPSstar Apr 25 '13 at 18:13
  • 1
    http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/pointer.html – Vishy Apr 25 '13 at 18:14
  • @TPSstar (*ptr)-4 gets the value ptr is pointing to and then subtracting 4. Ex. If *ptr = 15.04, then (*ptr) - 4 == 11.04. ptr-4, subtracts ptr (which is an address by 4*sizeof(ptr)), so it returns a new address. – Anil Vaitla Apr 25 '13 at 18:15
  • Yes exactly, so what if i use ptr instead of *ptr, imean ptr-4 so by this code which byte of memory will be accessible ? because initially the code reserved 8 bytes and pointer is pointing to First byte. what im asking is how to modify that code to access any desired byte let assume 4th byte of memory.. just as (ptr+1) will access 8+1=9th byte – TPSstar Apr 25 '13 at 18:29
  • 1
    no, ptr+1 will not access the ninth byte. if ptr is currently say address 10, then ptr+1 will be address 18, since the sizeof(ptr) is 8. Please read http://www.eskimo.com/~scs/cclass/notes/sx10b.html, or the link by Vishy – Anil Vaitla Apr 25 '13 at 18:38
  • If you haven't allocated memory for storing your pointed values, you can get an Exception or errors in your code. – Broken_Window Apr 25 '13 at 19:52

4 Answers4

8

You can access the bytes that represent an object by converting a pointer to the object to a pointer to unsigned char and then accessing bytes through that pointer. For example, the fourth byte of i could be set to 9 by:

unsigned char *p = (unsigned char *) &i;
*(p+4) = 9;

However, you should not do this without good reason. It runs into portability problems and should only be done for special purposes and with careful attention to the C standard and/or the documentation of your C implementation. If you explain further why you want to do something like this, it might be possible to show better ways of doing it or to explain the hazards.

Note that the correct address for byte four (starting numbering at byte zero) is p+4, not p-4 as used in the question.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Thanks that's actually what i was asking for :D – TPSstar Apr 25 '13 at 18:33
  • long double i, *ptr; ptr = &i; in this scenario what (char *)+ptr will do? – TPSstar Apr 25 '13 at 18:35
  • 1
    I am not sure what you are asking. If you are asking what happens if you add numbers to a `char *`, then the answer is it adds a number of bytes to the address (sort of, within certain bounds). If you are asking something else, I do not understand. `(char *)+ptr` is not a valid expression, because it contains `+ptr`, and you cannot apply unary `+` to a pointer. – Eric Postpischil Apr 25 '13 at 18:45
3

I would attempt something more readable

union {
    long double d;
    char v[sizeof(long double)];
} x;

x.d = 1234567890;
std::cout << x.d << ' ' << int(x.v[6]) << std::endl;
x.v[6] = 0xCC;
std::cout << x.d << ' ' << int(x.v[6]) << std::endl;

yields

1.23457e+09 44
1.23981e+09 -52
CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • 1
    The question is tagged C. `std::cout` does not exist in C. And aliasing through unions is not supported in standard C++ the way it is in C. – Eric Postpischil Apr 25 '13 at 18:19
  • @EricPostpischil It was tagged C by someone other than OP; we don't actually know what language they're using. – Darshan Rivka Whittle Apr 25 '13 at 18:20
  • you're right, I have at hand a C++ project and used that to test. Anyway, the suggestion should hold for C also. – CapelliC Apr 25 '13 at 18:21
  • @DarshanComputing: As my comment indicates, the code is broken either way: If it is C, `std::cout` does not work. If it is C++, the aliasing through a union is not supported. – Eric Postpischil Apr 25 '13 at 18:21
  • 2
    @EricPostpischil I'm not too handy with the standards. I assume you're probably right. g++ with the strictest flags I know of doesn't complain and it works just fine, so I think it's good of you to point out if this goes against the standard, but I still think it's a good answer. – Darshan Rivka Whittle Apr 25 '13 at 18:32
  • The C standard has some text stating that when a union member other than the last-stored member is accessed, the bytes are reinterpreted as the new type. There are some implementation-defined aspects of that, but it is permitted. The C++ standard does not have the same text. It says the bytes of an object can be copied to a character array and back, as by `memcpy`. So, if you want to be tinkering with object representations in “standard” C++, you ought to be copying bytes rather than using unions. – Eric Postpischil Apr 25 '13 at 20:09
0

(*ptr)-4 = 9 is not permitted because it leads to RValue violation (Right hand side of an assignment operation cannot be another operation).

But you can use bit operations like:

(*ptr) = (*ptr) & 0x00009000;

Vishy
  • 1,292
  • 12
  • 17
0

First see here: How do you set only certain bits of a byte in C without affecting the rest?. The idea is to clear the byte you are interested in, and then set your value with an or operation. So in your case you'd do:

val &= ~0xff;    // Clear lower byte
val |= 9 & 0xff; // Set Nine into the least significant byte. 
Community
  • 1
  • 1
Anil Vaitla
  • 2,958
  • 22
  • 31