Thread: Accessing variables with memory address

  1. #16
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Are you saying there is no way for me to get 0 to print?

    Using the code I posted, yes. I think I see what you did. You removed the dereference in my code and as a result you simply printed the address in base-10 (decimal), ie: 0x12ff5c (hex) == 1245020 (dec). Correct?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  2. #17
    Registered User ITAmember's Avatar
    Join Date
    Mar 2009
    Location
    Nebraska
    Posts
    72
    duh! What was I thinking, I just needed to add the asterisk to dereference the variable. :P New print statement:

    Code:
    printf("test1.type = %i, address = %#x\n", *((int *)(&test1)), (&test1));
    Prints 0. Thanks a ton!

  3. #18
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Sure, and FYI, you really don't need all those parenthesis. They're harmless, but unnecessary.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #19
    Registered User ITAmember's Avatar
    Join Date
    Mar 2009
    Location
    Nebraska
    Posts
    72
    Now I have a problem, I want to access the data member so I replaced that print statement with this one:

    Code:
    printf("test1.data = %i, address = %#x\n", *((int *)(&test1 + 1)), (&test1 + 1));
    This is what I get for output:

    Code:
    test1 0x12ff5c, type 0x12ff5c, data 0x12ff60
    test1.type = -858993460, address = 0x12ff64
    The single int I added counts for 64 bits on a 32 computer, any ideas what's up?

  5. #20
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> (&test1 + 1)

    Remember, when you add a value 'n' to a pointer, you get an value equal to (char*)address + (n * sizeof(type)). It works just like array indexing, eg: &test1 + 4 == &test[4]. So to get the value of test1.data, you would need to cast it to an int* first to yield the correct address. eg:

    Code:
    #include <stdio.h>
    
    /*
    	Make sure the structure doesn't get padded
    */
    #pragma pack(push, 1)
    typedef struct
    {
    	int type;
    	int data;
    } dynamic_int;
    #pragma pack(pop)
    
    int main()
    {
    	/*create a dynamic integer for tests*/
    	dynamic_int test1;
    	/* initalize the data members */
    	test1.data = 1024;
    	printf("&test1: %#x, &test1.data %#x, test.data: %i\n", &test1, &test1.data, *((int*)&test1 + 1));
    	return 0;
    }
    But again, for this sort of thing to work, you'll need to take steps to make sure that the compiler doesn't pad the structure.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #21
    Registered User ITAmember's Avatar
    Join Date
    Mar 2009
    Location
    Nebraska
    Posts
    72
    Works great now, thanks. If the struct is all 32 bit integers do I still need the #pragma pack?

  7. #22
    Registered User ITAmember's Avatar
    Join Date
    Mar 2009
    Location
    Nebraska
    Posts
    72
    This is to cool!

    Code:
    #include <stdio.h>
    
    typedef struct
    {
    	int type;
    	int data;
    } dint;
    
    typedef struct
    {
    	int type;
    	float data;
    } dfloat;
    
    typedef int object;
    
    int main()
    {
    	object test;
    	dint test_int;
    	dfloat test_float;
    
    	test_int.type = 0;
    	test_int.data = 1;
    	test_float.type = 1;
    	test_float.data = 2.5;
    
    	printf("assigning test_int to test\n\n");
    	test = (int)&test_int;
    	printf("the value of test = %i, the type of test = %i\n", *((int*)test+1), *((int*)test));
    	printf("adding 762 to test\n");
    	*((int*)test+1) += 762;
    	printf("the value of test = %i, the type of test = %i\n", *((int*)test+1), *((int*)test));
    	printf("\nassigning test_float to test\n\n");
    	test = (int)&test_float;
    	printf("the value of test = %f, the type of test = %i\n", *((float*)test+1), *((int*)test));
    	printf("adding 1.234 to test\n");
    	*((float*)test+1) += 1.234;
    	printf("the value of test = %f, the type of test = %i\n\n", *((float*)test+1), *((int*)test));
    	return 0;
    }
    100% dynamic typing! Thanks a lot guys.

  8. #23
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> printf("the value of test = %f, the type of test = %i\n", *((float*)test+1), *((int*)test));

    That works, but only by accident. sizeof(float)==sizeof(int) on most systems, but this certainly isn't always the case. The first member is an int, so to seek past it, you would need to cast to int*, add the value to the pointer, and then dereference the float* at that address. The correct cast would be:

    Code:
    *(float*)((int*)test + 1)
    Does that make sense?

    >> If the struct is all 32 bit integers do I still need the #pragma pack?

    I don't think you do, but it's probably a good idea, anyway (for the sake of consistency).
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  9. #24
    Registered User ITAmember's Avatar
    Join Date
    Mar 2009
    Location
    Nebraska
    Posts
    72
    So I want *(float*)((int*)test + 1) instead of *((float*)test+1)?

  10. #25
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Right, because *((float*)test+1) is saying that the first member is a float, which it isn't.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  11. #26
    Registered User ITAmember's Avatar
    Join Date
    Mar 2009
    Location
    Nebraska
    Posts
    72
    I see. One more question. Is the type casting slow? It looks to me that it's just so the compiler knows what type I'm working with. Is that correct? So test = (int)&test_float; should compile into two mov instructions? One to move data from RAM to register, another to move data from register to RAM?

  12. #27
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Another example:

    Code:
    #pragma pack(push, 1)
    struct test
    {
    	float f;
    	int i;
    	short s;
    };
    #pragma pack(pop)
    
    //...
    
    test t;
    short s = *(short*)((int*)((float*)t + 1) + 1);
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  13. #28
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    >> Is the type casting slow?

    No. The efficiency of the operation depends on the compiler, but generally, you won't see an performance difference whatsoever.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  14. #29
    Registered User ITAmember's Avatar
    Join Date
    Mar 2009
    Location
    Nebraska
    Posts
    72
    Is there any difference between a void pointer and the integers I'm using? They work exactly the same right?

  15. #30
    Registered User ITAmember's Avatar
    Join Date
    Mar 2009
    Location
    Nebraska
    Posts
    72
    I rewrote the test program to use malloc and void pointers. This should open up new possibilities. I would like you guys to review the code to see if I made any mistakes however. (don't worry, it does work)

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
    	int test;
    	void *test_int = malloc(8);
    	void *test_float = malloc(8);
    
    	*(int*)test_int = 0;
    	*(int*)((int*)test_int+1) = 1;
    	*(int*)test_float = 1;
    	*(float*)((int*)test_float+1) = 2;
    
    	printf("assigning test_int to test\n\n");
    	test = (int)test_int;
    	printf("the value of test = %i, the type of test = %i\n", *((int*)test+1), *(int*)test);
    	printf("adding 762 to test\n");
    	*((int*)test+1) += 762;
    	printf("the value of test = %i, the type of test = %i\n", *((int*)test+1), *((int*)test));
    	printf("\nassigning test_float to test\n\n");
    	test = (int)test_float;
    	printf("the value of test = %f, the type of test = %i\n", *(float*)((int*)test+1), *((int*)test));
    	printf("adding 1.234 to test\n");
    	*(float*)((int*)test+1) += 1.234;
    	printf("the value of test = %f, the type of test = %i\n\n", *(float*)((int*)test+1), *((int*)test));
    
    	free(test_int);
    	free(test_float);
    	return 0;
    }
    Last edited by ITAmember; 06-26-2009 at 02:55 PM. Reason: typeo

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Mutex and Shared Memory Segment Questions.
    By MadDog in forum Linux Programming
    Replies: 14
    Last Post: 06-20-2010, 04:04 AM
  2. Assignment Operator, Memory and Scope
    By SevenThunders in forum C++ Programming
    Replies: 47
    Last Post: 03-31-2008, 06:22 AM
  3. Printing out the memory address
    By Scalpel78 in forum C++ Programming
    Replies: 16
    Last Post: 01-09-2007, 11:01 AM
  4. Changing memory address
    By tzpb8 in forum C Programming
    Replies: 3
    Last Post: 07-26-2006, 09:50 AM
  5. Pointer to specific memory address
    By elnerdo in forum C++ Programming
    Replies: 10
    Last Post: 05-19-2006, 07:35 AM