Question:
C programming memory addresses of variables?
bill k
2012-12-22 08:44:45 UTC
Hello. I know that I can print out the starting address of a variable in memory using &. If I have an integer which is 4 bytes long is it possible to somehow see the address and contents of each of the 4 bytes separately?

now this got me thinking...how many numbers can I fit into an integer variable? I remember something about 2^34 but how many digits does that translate to?

int number=123456789;

&number would be the first address
int *ptr;
ptr=number;
&number is the address of where to variable number starts.
*ptr this is the contents of the the thing that pointer points to//it will show the contents of the variable across all 4 bytes

what if I want to access byte 2 or byte 3? is this possible?
Seven answers:
Ratchetr
2012-12-22 09:34:09 UTC
Code below uses a pointer rather than bit shifting.



In C, a char is always 1 byte. So you can cast a pointer to int to a pointer to char, then access each individual byte through the char pointer.



Also printed out the minimum and maximum int value. There are constants defined for these in limits.h



See link below to view the output of this code:



#include

#include



int main(void)

{

    int i,number = 0x12345678;



    char *p = (char *)&number;



    printf("Address of number is: %p\n",&number);



    for(i=0;i
    {

        printf("Address %p = %x\n",p+i,*(p+i));

    }



    printf("Smallest int is %d\n",INT_MIN);

    printf("Largest int is %d\n",INT_MAX);

    return 0;

}
green meklar
2012-12-22 23:28:07 UTC
>If I have an integer which is 4 bytes long is it possible to somehow see the address and contents of each of the 4 bytes separately?



Absolutely.



>how many numbers can I fit into an integer variable? I remember something about 2^34 but how many digits does that translate to?



In general, an X-bit signed two's complement integer can store from -(2^(X-1)) to (2^(X-1))-1. For a 32-bit int, this translates to -2147483648 to 2147483647 in decimal. This is no more than 10 digits, although counting the minus sign for negative numbers, it comes to 11 digits.
?
2012-12-23 12:22:54 UTC
You are right about the & providing a pointer to the starting address. In fact, the standard says:



        When a pointer to an object is converted to a pointer to a character

        type, the result points to the lowest addressed byte of the object.

        Successive increments of the result, up to the size of the object, yield

        pointers to the remaining bytes of the object.



Which is clear enough, except it doesn't state the endianness. So the lowest addressed byte may carry higher order or lower order significant bits. The language doesn't say anything about that.



The C standard says this about bytes:



        A byte is composed of a contiguous sequence of bits, the number of

        which is implementation-defined. The least significant bit is called

        the low-order bit; the most significant bit is called the high-order bit.



It also says that size of a char must be 1 byte and that a byte must be at least 8 bits. Other than bit fields, it also says that all objects must be an integral number of bytes in size. But again, a byte can be more than 8 bits. On the PDP-10, which is a 36-bit word machine using 18-bit addressing (I think), a C implementation would probably use 9-bit char/bytes. But 12, 18, and 36-bit chars would also meet the standard.



Assuming you don't want to trust limits.h and assuming that there aren't any padding bits, you can write some code to verify the number of bits in a byte:



int bits( void ) {

    unsigned int count;

    unsigned char c= -1;

    for ( count= 0; c != 0; ++count ) c &= c - 1;

    return count;

}



(Yes, I assign a signed number to an unsigned char, a conversion for which the standard clearly defines in detail.)



However, an implementation may actually use padding bits. For example, the above PDP-10 may specify that an unsigned char occupies 9 bits in memory (four per word) but may also specify that the "value bits" are 8 and the "padding bits" are 1. So you actually may not be able to access the padding bits to find out their existence without doing non-standard tricks. (They won't be mentioned in limits.h and you can't write standard C code to find out about them, either.)



The addresses of variables are not separately stored in other variables, unless you specifically set up new variables for that purpose. "Seeing" an address means computing it. Since every object in C must be an integral number of bytes in size and since the pointer formed by using & must give you the lowest address value of the object, it follows that each successive byte will be at an address exactly 1 higher than the prior one. You can use sizeof() to determine how many. Padding bits, though, you cannot ever see. (Alignment bytes used to pad out objects in structures or between structures you may be able to, though.)



You can always cast a pointer to an object with sizeof() larger than 1 to a char * pointer and access successive bytes. But in general, because of allowed endian differences and because of the possibility of padding bits permitted by the standard, you can't know how to interpret what you see if you do that or even if you will get every bit in the process. For example, in the 36-bit case where a char is 8 value bits plus 1 pad bit and sizeof(int)=4, you could convert the int * pointer to a char * and access four successive 8-bit values and find that you've only got 32 bits, not 36 bits. So you wouldn't even be able to get all 36-bits of the valid int that way.



The point here is that while things usually work in ways you would naturally guess they would, there exist machines and compilers where such assumptions would get you into trouble. Most of the examples you were given here make assumptions that would not be true on a PDP-10, for example. Just be aware. But have fun, too!
girl Graspacious
2012-12-22 09:46:27 UTC
The max range of an integral number can be 2^16= 65,536.



Since there are both positive and negative integer values, range of an integer can be from ---> 32,767 to -32,767.



So the number value you specified would be too long for an integer and result in an error. You will have to use double or long, i think.





This is the decimal value. But data is stored in form of hexadecimal values. 32,767 is stored as 7fff in hexadecimal format.



Here you have specified the number as the location in the memory. If you want to use &number as the memory location and number as the content, you should write,



P= &number;





Also, an integer pointer extracts two bytes at once. So, there you go. At once, you will get two bytes of content. An integer value is always only 2 bytes long.



To get the next two bytes(which will not be your number, mind you), you can increment the pointer- p++. And you will get next 2 bytes if you print- *p.







Hope you got it!







EDIT: on seeing other answers, i see you people work on 32 bit compiler. I used to practice on 16 bit compiler, so the range is 2^16 for 16 bit compiler.
Empire539
2012-12-22 09:25:41 UTC
A typical int can hold 2³² values (ranging from 0 to 2³²−1 (4,294,967,295) unsigned, or from -2,147,483,648 to 2,147,483,647 signed).



And yes, you can access different parts of an int.



Before getting into the code, though, let's break it down mathematically so we know what to expect. Taking your example:

123,456,789 (base 10) would translate to 0000111 01011011 11001101 00010101 (base 2).

This, in turn, would be represented in hexadecimal as 75BCD15.



Thus, if we print out the contents of that int as hex, 75BCD15 is what we should expect to get. So:



int num = 123456789;



int i;

for (i = 0; i < 4; i++) {

    int numPart = (num >> (8*i)) & 0xFF;

    printf("%x\n", numPart);

}



The above code prints out the following:

15

cd

5b

7



Since I ran this code on my computer, which has an Intel x86-64 processor, the byte order came out as little-endian. Thus, the correct ordering would be 75bcd15, which is exactly what we expected.
2016-05-18 07:55:41 UTC
Depends on your operating system. Back in DOS days, I'd write my own TSR (Terminate & Stay Resident) programs running off the system clock interrupt, which would check my health points and mana points in role-playing games, and adjust them when they got low. There was no protection for memory, so I could access any memory I pleased if I had the address. In modern operating systems, such as Windows 95 and up, applications get their own memory spaces. I don't know how to access memory which belongs to another process, sorry. There're probably Windows functions that would let you access it, if you had the process id and address. *shrug* Sorry, I don't know the name of the function or its parameters.
2012-12-22 09:21:41 UTC
if you want to write to each byte of an int individually, you can do this using bitwise operations

you can also cast your int pointer to a character pointer, like so



#include

using namespace std;



int main(){

int number=0xFAFBFCFD;

char *n;

n = (char*)&number;

cout << hex << number << endl;



for(int i=0; i<4; i++)

cout << hex << (n[i] & 0xFF)<< endl;;



cin.get();

return 0;

}



/*

output

fafbfcfd

fd

fc

fb

fa

*/


This content was originally posted on Y! Answers, a Q&A website that shut down in 2021.
Loading...