2

Had a question to print the addresses of the values:

char word[] = "hi there"; //print address of string
int a = 1; // print address of 1

I know how to print the addresses of the variables and I thought the value is within the variable address? So the address of the value is actually the variable address?

Is this a trick question and I am correct?

Thanks in advance

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
Newbie
  • 1,677
  • 2
  • 12
  • 14

6 Answers6

9
char word[]="hi there"; //print address of string

word is the name of an object called char array. It has an address and a size.

On this address, there is the first element, a char with the value 'h'. The following letters follow at the next addresses, up to the last 'e'. This one is followed with a 0 byte, the string terminator. So the total size of the array is 9: 8 given chars plus a 0 byte.

+--+--+--+--+--+--+--+--+--+
|h |i |  |t |h |e |r |e |# | <-- # means NUL byte.
+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+
|68|69|20|74|68|65|72|65|00|
+--+--+--+--+--+--+--+--+--+

Here we have one specialty: &word and word point to the same address, but the size of what they represent is different. &word points to the whole array, so sizeof(*(&word)) is 9, while word points to the first character, so sizeof(*word) is 1.

It is said that "word decays into a pointer" to the first element.

As asked in the comments, note that this is slightly different from the case

char * wordptr = "hi there";

as the memory layout is the same, but the string lies in readonly memory, while the normal data segment contains a pointer pointing to that string. So &wordptr, wordptr and *wordptr are completely distinct from each other: &wordptr is a char ** pointing to data memory, wordptr is a char * pointing to RO memory (i.e., to the real string - to be exact, to the first character of the string) and *wordptr is just the 'h' at the beginning.

OTOH,

int a = 1; // print address of 1

a is the name of an object called int. It as well has an address and a size.

Its size is implementation-dependent, its memory layout as well. Let's take a little endian machine where the lowest byte comes first, and let's assume we have 4 bytes per int:

+--+--+--+--+
|01|00|00|00|
+--+--+--+--+

You can take the address of both of them with &word and &a and print them out:

printf("%p %p\n", &word, (void *)&a);

((void *) is needed because on some implementations, the sizes of the pointers can vary, so in order to be on the safe side, we need to cast the pointer type.)

The term "address of 1" doesn't make sense; while the variable whose address you get with &a holds the value 1, this is mere "coincidence": you may set a = 3, and the address remains the same, while the value stored there changes. So it is indeed better to say "address of a variable corrently holding 1".

glglgl
  • 89,107
  • 13
  • 149
  • 217
  • Better very helpful, but your have typo `%a` should be `&a` in printf(), also you need to typecase to `void*` for at leas int object `a` – Grijesh Chauhan Oct 16 '13 at 14:39
  • Nice answer, particularly the last paragraph. – WhozCraig Oct 16 '13 at 14:41
  • @GrijeshChauhan Do you mean because the sizes of the pointers could vary? – glglgl Oct 16 '13 at 14:46
  • @glglgl I read documentation it was mentioned that with `%p` we need to cast address to `void*` otherwise it would be undefined behavior(technically I am not very much clear why this constrain imposed). Yes as I know we don't need to cast `char*`. – Grijesh Chauhan Oct 16 '13 at 14:48
  • @GrijeshChauhan AFAIK there is a chapter in the C standard which states that `void *` and `char *` are allowed to have a different layout than other pointer types (and there are indeed some architectures which have this specialties). – glglgl Oct 16 '13 at 14:59
  • @glglgl indeed question was very silly but your answer made it supper helpful (add some/that language standard related to it, if you think). – Grijesh Chauhan Oct 16 '13 at 15:03
  • @glglgl What about the case for char*word="Hi there"; ? Would the address of the string value be printf("%p",word);? – Newbie Oct 16 '13 at 15:11
  • 1
    @Newbie `word` is address of first element where as `&word` is address of complete array. To understand it you may read my answer: [What does `sizeof(&array)` return?](http://stackoverflow.com/questions/15177420/what-does-sizeofarray-return/15177499#15177499) – Grijesh Chauhan Oct 16 '13 at 15:24
  • @GrijeshChauhan I have just read it and I understand what you meant. But isn't &word getting the address of the pointer itself and not the address of the complete array? So if I was asked to "Print the address of "Hi there"", what should be the answer? – Newbie Oct 16 '13 at 15:32
  • @Newbie That is exactly the difference between `char *`, which is a separate pointer variable, and `char []`, which decays into an address if used as such. – glglgl Oct 16 '13 at 15:34
  • @Newbie The address of `"Hi there"` can be obtained with both `word` and `&word` (at least in the array case), as both addresses are the same, only their type is different. Better use `word`, however, as it then still works if you change it to a `char *`. – glglgl Oct 16 '13 at 15:37
  • @glglgl I'm guessing that is a yes? Because I considered char*word as a pointer to the actual location storing "Hi there". So if I run printf("%p",word);, would I print the address of the string literal? – Newbie Oct 16 '13 at 15:38
  • @Newbie yes, exactly. In the case of a `char *` you are right. – glglgl Oct 16 '13 at 15:39
  • @glglgl because the question coupled this "char*" question and the ones I mentioned earlier, all in printing the values. I figured that I can only print the address of the values for "char*" and not the ones mentioned earlier, hence I didn't asked. I guess the ones mentioned earlier are just to trick me, but not for the case of "char *". Really appreciate your help. Thanks. – Newbie Oct 16 '13 at 15:44
  • @glglgl; `&word is a char **` : I think you mean `wordptr`. Because `&word` is of type `char (*)[]`. – haccks Oct 16 '13 at 16:31
  • 1
    @haccks Very right. I itroduced `wordptr` quite late to distinguish it from `word` and forget to change it everywhere where appropriate. – glglgl Oct 16 '13 at 16:33
  • @glglgl; AFAUK; Saying `wordptr` is pointing to the real string is not correct. It should be: *`wordptr` is pointing to the **first `char`** of the string*. By the way good explanation. +1. – haccks Oct 16 '13 at 16:55
  • @haccks No. `*wordptr` *is* the first `char` of the string. `wordptr` points to it. – glglgl Oct 16 '13 at 16:56
  • @haccks That's what I first read from your comment. But now I see that there was a mismatch of `*`s which you corrected later. My misunderstanding. Meanwhile, I changed my wording a bit. – glglgl Oct 16 '13 at 17:00
  • @glglgl; Now it is much better. – haccks Oct 16 '13 at 17:04
4

If you are talking of printing the address of the values to the right of the equals sign, then it is a trick question.

The values to the right of the equals sign are calld initialisers.

Initialisers are not required to (meaning it is up to the compiler whether they) have an address and in your case you don't have access to it even if they have one.

If you are talking about the address of the variables a and word then the question is trivial, because they will have an address if you reference it.

Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82
3

A picture might help. I took your declarations

char word[] = "hi there";
int a = 1;

and put them in a simple program, then used a small utility I wrote to display the layout of those items in memory. I get the following memory map on my system at work (SLES 10, gcc 4.1.2):

           Item        Address   00   01   02   03
           ----        -------   --   --   --   --
     "hi there"       0x400a32  'h'  'i'   20  't'
                      0x400a36  'h'  'e'  'r'  'e'
                      0x400a3a   00  '0'  '1'   00

           word 0x7fffb48d2ee0  'h'  'i'   20  't'
                0x7fffb48d2ee4  'h'  'e'  'r'  'e'
                0x7fffb48d2ee8   00   00   00   00

              a 0x7fffb48d2edc   01   00   00   00

Unlike numeric literals, storage is set aside for string literals. This storage is visible over the entire program and held over the program's lifetime (it has static storage duration). This storage may or may not be writable, depending on the platform; it's best to assume it isn't. You should never try to modify the contents of a string literal, and attempting to do so invokes undefined behavior.

The string literal "hi there" has 9 bytes set aside for it starting at address 0x400a32 and ending at address 0x400a3a (the bytes at 0x400a3b through 0x400a3d are not part of the string and contain some random values).

The character array word also has 9 bytes set aside for it starting at address 0x7fffb48d2ee0. The contents of the string literal have been copied to it.

The integer variable a has 4 bytes set aside for it starting at address 0x7fffb48d2edc and it contains the value 1 (0x00000001). Like I said earlier, no storage is set aside for numeric literals like 1; the compiler would simply have generated the code to load the value into a.

The system I am working on is little-endian, meaning that multi-byte values have the least-significant byte (0x01) stored at the low address (little-endian systems read "right-to-left"). On a big-endian system, the least significant byte would be stored at the high address (big-endian systems read "left-to-right"). Again, a picture might help - if we were storing the binary value 0x12345678, the individual bytes would be stored at address A as follows:

Big endian:       A+0  A+1  A+2  A+3
Value:            0x12 0x34 0x56 0x78
Little endian:    A+3  A+2  A+1  A+0

Note that in this case, a is stored at a lower address than word, even though it was declared after word in the source code. Don't assume that variables are laid out in memory in the same order that they were declared.

John Bode
  • 119,563
  • 19
  • 122
  • 198
2

Did you tried to check print pointers. I think that may help you.

The address is printed using %p From the specs:-

p The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.

To print address in pointer to pointer use like this:-

printf("%p",x)

In linux you can use plain gdb to see the memory address

Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
2

& is the "address-of" operator which generates a pointer to its operand.

Hence, &a is a valid pointer expression which holds the address of the variable a and hence the value of this pointer be printed with the below statement.

printf("Address of a: %p",(void*)&a);

Similarly if you want the pointer to the whole word[] array you could print by:

printf("Pointer to Whole array: %p",(void*)&word);

If you will want the address of the first element in the word[] array you could print that by

printf("Address of first element in the word[]: %p",(void*)word);

Well you might print and see above two printf() statements provide you the same address, but they are different. Read this

Note:

If the operand of & has the type type, the result is pointer to type.

  • Result of &a is pointer to int

  • Result of &word is pointer to array of 9 char . Since size of (*(&word)) is 9

  • Reference to word has type pointer to char.

Community
  • 1
  • 1
smRaj
  • 1,246
  • 1
  • 9
  • 13
0

You can print the address of variables using the & operator:

int a = 1; 
printf("Address of variable a is: %p",&a);
Paddyd
  • 1,870
  • 16
  • 26
  • it's %p if you want to print the address – tristan Oct 16 '13 at 14:33
  • The C standard requires to pass `void*` when using `%p`. So this is one of the rare cases where casting is required (to meet the standard). – alk Oct 16 '13 at 17:22