user3577478
user3577478

Reputation: 91

How to print out memory addresses of C-String?

The function prints the addresses of each memory location of the dynamic array. Is this the right way?

int main()
{
    char str[] = "This is a test";
    printAddresses(str, strlen(str));
}

template <class type>
void printAddresses(type *item, int n)
{
    cout << "Printing Addresses..." << endl;
    for (int i = 0; i < n; i++)
    {
        cout << "Index " << i << ": " << ((&item) + i)  << endl;
    }

}

I've also heard that I should use:

cout << "Index " << i << ": " << (void*) &item[i] << endl;

but that gives me different memory address. I'm not sure which one is right.

Upvotes: 1

Views: 2612

Answers (4)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726519

The correct address is the one you obtain when printing (void*)&item[i].

item is already a pointer; so is &item[i]. You are interested in printing the value of this pointer, you need to cast it to void* before calling << on it.

When you print ((&item) + i) you are making an extra level of indirection (&item is a pointer-to-pointer), so you print the address of item-the-pointer, not the address of what item is pointing to.

Note:: Starting with C++11 you can use std::addressof function in place of operator & for better readability and to avoid potential issues when T provides an overload for operator &:

cout << "Index " << i << ": " << std::addressof(item[i]) << endl;

Upvotes: 1

Sam Varshavchik
Sam Varshavchik

Reputation: 118310

The reason you get a different memory address is because your code is wrong.

void printAddresses(type *item, int n)

item is a pointer parameter to your printAddresses template function. So, in the following expression:

    cout << "Index " << i << ": " << ((&item) + i)  << endl;

Therefore:

&item

becomes the address of the parameter to your template function, and not the address of the array.

This is why:

 (&item)+i

is wrong, and is utterly meaningless. The address of the parameter to your template function is not really very useful, here.

 (void*) &item[i]

Is the correct answer.

Upvotes: 0

gsamaras
gsamaras

Reputation: 73366

Run this:

#include <iostream>
#include <cstring>
using namespace std;

template <class type>
void printAddresses(type *item, int n)
{
    cout << "Printing Addresses..." << endl;
    for (int i = 0; i < n; i++)
    {
        cout << "Index " << i << ": " << ((&item) + i)  << endl;
        cout << "Index2 " << i << ": " << (void*) &item[i] << endl;
    }

}

int main()
{
    char str[] = "This is a test";
    printAddresses(str, strlen(str));
}

which in my machine prints:

gsamaras@gsamaras-A15:~$ g++ -Wall main.cpp
gsamaras@gsamaras-A15:~$ ./a.out
Printing Addresses...
Index 0: 0x7ffd5c9ead58
Index2 0: 0x7ffd5c9ead90
Index 1: 0x7ffd5c9ead60
Index2 1: 0x7ffd5c9ead91
Index 2: 0x7ffd5c9ead68
Index2 2: 0x7ffd5c9ead92
Index 3: 0x7ffd5c9ead70
Index2 3: 0x7ffd5c9ead93
Index 4: 0x7ffd5c9ead78
Index2 4: 0x7ffd5c9ead94
Index 5: 0x7ffd5c9ead80
Index2 5: 0x7ffd5c9ead95
Index 6: 0x7ffd5c9ead88
Index2 6: 0x7ffd5c9ead96
Index 7: 0x7ffd5c9ead90
Index2 7: 0x7ffd5c9ead97
Index 8: 0x7ffd5c9ead98
Index2 8: 0x7ffd5c9ead98
Index 9: 0x7ffd5c9eada0
Index2 9: 0x7ffd5c9ead99
Index 10: 0x7ffd5c9eada8
Index2 10: 0x7ffd5c9ead9a
Index 11: 0x7ffd5c9eadb0
Index2 11: 0x7ffd5c9ead9b
Index 12: 0x7ffd5c9eadb8
Index2 12: 0x7ffd5c9ead9c
Index 13: 0x7ffd5c9eadc0
Index2 13: 0x7ffd5c9ead9d

Now think what sequence you expect to see for stored chars? You expect every character to be adjacent to the previous one (of course) and every one to take 1 memory cell. That should tell you that:

(void*) &item[i]

is the right thing to do.


Also notice that zmbq's comment, about using a debugger to find out makes sense too.


Finally, I would advice you to read: Printing array element memory adresses C and C++, why different output?

Upvotes: 1

A possible way could be to use the C-style printf with %p. So include <cstdio> then try for example:

 const char *sp = "abcde" + 2; // some computation giving a string address
 printf("sp=%p ('%s')\n", sp, sp);

Alternatively, cast to (void*) and use usual

std::cout << "sp at " << (void*)sp << std::endl;

Upvotes: 0

Related Questions