Finding memory address for characters

I've recently been reading tutorials on arrays and their aquaintance with memory addresses. So, I completely understand how an array's name, when defined, is a constant pointer to its first element's address.

My problem, however, lies with characters, and how they are basically arrays except with a null terminator for the last index. What I've come to undestand, is that, when defining a character variable, each 'character' has a memory address it is associated with.

For example:
 
char name[] = {"Hello"}; // | 'H' | 'e' | 'l' | 'l' | 'o' | '/0' | 

An address holds the value of 'H'.
An address holds the value of 'e'.
An address holds the value of 'l' and so on.

I have come to believe this is false, however. Mainly from a simple std::cout command.
1
2
std::cout << &name    << std::endl; // attempt 1
std::cout << &name[0] << std::endl; // attempt 2 

The first attempt, as I assumed, should print the address of the first element.
The second attempt, as I assumed, did not. I figured, &names[0] would print the address of the first element, which should have been the same as &names.

So, this brings me to my question, are characters formed of constant addresses, or are the address of individual characters not reachable? I'm heavily confused as to what might be happening concerning this issue.

Thanks for reading, and I hope someone can shed some light upon me.
closed account (Dy7SLyTq)
no thats not the issue. its because name is technically a * (ie char *name = "Hello") which points to an adress that holds the string "Hello". so your initial assumption was correct. idk why it wont print for you, as i have never needed to do it. just out of curiousity why do you need to do it? just curiousity? try doing std::cout<< *name << std::endl;
> An address holds the value of 'H'.
> An address holds the value of 'e'.
> An address holds the value of 'l' and so on.

No. A byte (char) holds the value of 'H'. That byte (char) has an address.

> or are the address of individual characters not reachable?

To print out the address of a single character, convert the pointer to char (char*) or pointer to const char (const char*) to a pointer to const void (const void*).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>

int main()
{
    char name[] = "Hello" ; // | 'H' | 'e' | 'l' | 'l' | 'o' | '/0' |
    // name is an array of six chars

    // &name is the address of the array of six chars
    std::cout << &name << '\n' ;

    const char* pc = &( name[0] ) ;
    // pc is a pointer to the char at position zero ('H')

    // prints out the null terminated c-string "Hello"
    std::cout << pc << '\n' ;

    const void* pv = pc ;
    // pv contains the address pc (address of the char at position zero)

    // prints out the address of char 'H' in the array
    std::cout << pv << '\n' ;

    // print out every char in the array along with its address
    for( int i = 0 ; i < sizeof(name) ; ++i )
    {
        char c = name[i] ;
        const void* pv = &( name[i] ) ;
        if( c != 0 ) std::cout << "char " << c << " is at address " << pv << '\n' ;
        else std::cout << "null charater is at address " << pv << '\n' ;
    }
}

http://ideone.com/DLaxc4
Ok, so, as you said, name is a pointer which points to an address that holds the string "Hello".
Thank you, that makes sense now. I could always print the address of the "full string," but I thought the series of characters were made of seperate memory addresses. I was curious mainly because I was trying to completely understand arrays and characters.

EDIT: std::cout << *names << std::endl;
This only prints out the value stored in the memory address. Which in this case would be 'H'. That's mainly why I was confused. Because if *names printed out the value of the address of the first element, then why does *(names + 1) print out 'e' when the series of characters are monitored by a single address.

EDIT 2: Currently reading JLBorges's post. Thanks for replying, by the way.

EDIT 3: Excellent. Though, I don't understand the use of the const and void in regards to this problem, but hopefully, I will be able to soon. Just have to do more reading.

Basically, as you've said, JLBorges, each character of a "string" is held by a byte. This byte has an address in memory. Is there a reason the individual character addresses were so unatainable (or at least by beginners such as myself)?
Last edited on
An output stream (for instance std::cout) gives special treatment to pointers to char (<<). It assumes that the pointer points to the first character of a c-style string (a sequence of characters terminated by a null character), and that what we want to do is print the entire c-style string. It prints every character starting at the first character pointed to, untill it gets to a null character.

For a pointer to anything else, it prints a human readable representation of the address.

With a pointer to void, void*, the information about the type of the variable that the pointer actually points to is lost; the output stream does not have the knowledge about what it points to; and it just prints out an address.

1
2
3
4
char* pc = &c ; // pc points to a variable of type char

void* pv = pc ; // pv points to a variable, 
// but pv provides no information about what the type of that variable is  


In the simplest terms, const in const char* means: we have a pointer to char, and that char is not modifiable if reached via this pointer (logically const).
const in const void* means: we have a pointer to a variable of an unknown type, but that variable is not modifiable if reached via this pointer.
closed account (Dy7SLyTq)
sorry my mistake. i was getting my grammar mixed up
it's a little bit confusing if you are using your example to explain this question.
if it looks like this, the result will be different,
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

int main(void) {
	// your code goes here
	char* s = NULL;
	printf("%u\n", &s);

    const char* t = "ABC";
    s = t;
    printf("%u\n", &s);
    printf("%u\n", &(s[0]));
	return 0;
}


http://ideone.com/JUs0c4

so, there is no relationship between the address of a char*, and the address of the first element of this char*.
Don't do this:
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

// gcc 4.9 with -Wextra

int main()
{
    char* s = NULL;
	printf( "%u\n", &s ) ; // warning: format '%u' expects argument of type 'unsigned int',
	                       // but argument 2 has type 'char**'
}


printf() is type-unsafe, correctness is the programmer's responsibility.

If you are programming in C++, use the C++ stream library.
Unless we are forced to program in C, we do not want to write dreadful stuff of this kind, do we?

1
2
3
4
5
6
7
8
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

void foo( const char* pc, const void* pv, int_fast8_t fi8, uint32_t u32 )
{
     printf( "%s %p %" PRIdFAST8 " %" PRIu32 "\n", pc, pv, fi8, u32 ) ;
}


thank you, JLBorges, I just tried to give the example to show the address of the pointer of an array has no relationship with the address of the first element in the array., so force output address to unsigned int in printf is more simple.
1
2
3
4
5
6
7
8
9
10
11
#include <cstdint>
#include <iostream>

int main()
{
    int i = 7 ;
    int* p = &i ;

    // print the value of pointer p as an unsigned integer
    std::cout << std::uintptr_t(p) << '\n' ;
}
Topic archived. No new replies allowed.