#include <iostream>
using namespace std;
void test_func(char *data,int length)
{
cout<<"data:"<<data<<endl;
cout<<"length:"<<length<<endl;
void *addr=data;
cout<<"*addr:"<<addr<<endl;
cout<<"Address of data:"<<&data<<endl;
cout<<"data again:"<<*(&data)<<endl;
}
int main()
{
char msg[]="Hello world!";
test_func(msg,6);
return 0;
}
I was trying some other program where I came accrross void *addr=data. so I tried to understand it by writing a separate program for it. And here I am not able to understand what is the value stored in addr. I got the output of following program as:
data:Hello world!
length:6
*addr:0x794e0553d310
Address of data:0x794e0553d2e8
data again:Hello world!
Any help would be appreciated. Thanks in advance.
operator << is overloaded for cout, so if you pass a char* it prints the content (even though char* is a pointer).
However, if you pass a void pointer (addr in your example) it will print the address itself. So addr is the address of the first element of the message.
On the other hand, &data is a pointer to a pointer, so cout prints the address of data (with data being a pointer to your message).
When an array designator is passed to a function as an argument it is converted to a pointer to its first element.
Function parameters are local variables of the function.
Thus you can imagine function test_func along with its call as test_func(msg,6); the following way
void test_func( /* char *data,int length */)
{
char *data = msg;
int length = 6;
cout<<"data:"<<data<<endl;
cout<<"length:"<<length<<endl;
void *addr=data;
cout<<"*addr:"<<addr<<endl;
cout<<"Address of data:"<<&data<<endl;
cout<<"data again:"<<*(&data)<<endl;
}
In this case expression &data used in statement
cout<<"Address of data:"<<&data<<endl;
is the address of function local variable data
Accotding to the output
Address of data:0x794e0553d2e8
variable data is placed at address 0x794e0553d2e8 inside the function. The variable itself contains the address of the first character of array msg because it was assigned such a way when the function was called.:)
char *data = msg;
So the address of the variable data and the value stored in the variable differ.
As for this expression
*(&data)
then it is equivalent to expression
data
Thus statement
cout<<"data again:"<<*(&data)<<endl;
outputs the string the address of the first character of which is stored in pointer data.
operator << is overloaded for pointers of type char * It considers the object pointed to by such a pointer as a string and outputs it accordingly. Take into account that &data has type char **. It is not the same as char *. So for pointers of type char ** (and of other types) there is used overloaded operator << that interpretates such pointers as const void * and simply outputs the corresponding value.
data is a pointer to the first char of a string, which is how strings are implemented in C. When you assign it to addr, you are just getting rid of the static type of data.
The reason you get different results when you output addr and data is that std::cout treats char* as a special case: it is output as a string rather than having its pointer value printed. void* doesn't share this, so you just see the address.
void *addr=data"
When you write above statement, addr is a pointer of type void* and which has an address in memory. And it will be different from the address of the variable data of type char*. So when you print as follows
cout<<"*addr:"<<addr<<endl;
cout<<"Address of data:"<<&data<<endl;
Each statement will print corresponding address of those variables.
*addr=data;
The above statement will not change the address of variable addr instead it will redirect the address location of addr to the address location of data.
Related
I've been following CS50 and I'm pretty sure I keep hearing that a pointer is just an address
And that the address of an array is just the address of the first item in that array
But when I run the following code:
// we can also just create strings we need by using char * like this
char *name = "Emma 123";
char *another_string = "4";
printf("This is the string we get from name: %s\n", name);
// Print the value of the pointer pointing to name
printf("This is the pointer we get from name: %p\n", name);
// Now print out the address of the first letter in Emmas name
printf("This is the pointer we get by resolving &name: %p\n", &name);
printf("This is the pointer we get by resolving &name[0]: %p\n", &name[0]);
printf("Hmmmm. There is something different between &name and &name[0]. Somehow, I thought they should be the same ")
I get this as the output:
This is the string we get from name: Emma 123
This is the pointer we get from name: 0x4007ad
This is the pointer we get by resolving &name: 0x7ffd2d7d5468
This is the pointer we get by resolving &name[0]: 0x4007ad
I've been reading background articles but somehow, I can't seem to grasp why &name and &name[0] aren't the same
edit: I removed the c++ tag as I had incorrectly assumed these elements were common to c and c++
edit: I then added it back as it appears someone else did the same then decided it was a bad idea. Trying not to offend people
char *name = "Emma 123";
name stores the address of first element ('E').
&name is the address of name. It is a pointer to pointer.
&name[0] = &(*(name+0)) = (address of first element) = name
&name is the memory location of the pointer to your array.
&name[0] is the memory location of the first char in your array.
Note: as this is a multi-tagged C/C++ question: this answer applies to C++
From Member access operators:
Built-in subscript operator provides access to an object pointed-to by the pointer or array operand. [...]
The built-in subscript expression E1[E2] is exactly identical to the expression *(E1 + E2) [except evaluation order (since C++17)], that is, the pointer operand (which may be a result of array-to-pointer conversion, and which must point to an element of some array or one past the end) is adjusted to point to another element of the same array, following the rules of pointer arithmetics, and is then dereferenced.
meaning &name[0], which is &(name[0]) is equivalent to &(*name).
Also note that string literals should be constants (and your compiler should either reject your program, or emit a warning about non-conformant C++). Corrected example (C++, not C):
#include <iostream>
int main() {
const char * name = "Emma 123";
std::cout << name << "\n"; // Emma 123
std::cout << &name << "\n"; // 0x7ffd2d7d5468
std::cout << &(*name) << "\n"; // Emma 123
std::cout << &(name[0]) << "\n"; // Emma 123
}
As name is a pointer, &name, which takes the address of the pointer, is a pointer to a pointer.
#include <type_traits>
const char * name = "Emma 123";
static_assert(std::is_same_v<decltype(&name), const char **>);
static_assert(std::is_same_v<decltype(&(*name)), const char *>);
static_assert(std::is_same_v<decltype(&(name[0])), const char *>);
Now, whilst std::basic_ostream<CharT,Traits>::operator<< has a overload with a function parameter const void *, it has a non-member overload or for const char*
Character and character string arguments (e.g., of type char or const char*) are handled by the non-member overloads of operator<<.
Thus, for const char* arguments, the non-member overloads will chosen, which will print the characters from the character array whose first element is pointed to by the const char* pointer.
For const char**, however, the member const void* will be chosen:
std::cout << &name << "\n"; // 0x7ffd2d7d5468
std::cout << static_cast<const void*>(&name) << "\n"; // 0x7ffd2d7d5468
For C++ (I don't know C, but I do know that this code is different whether it is C or C++):
String literals are constant. It should be
const char *name = "Emma 123";
That aside, name is already the pointer to the first element in the array. You get expected output with:
#include <iostream>
int main(){
const char* name = "Emma";
std::cout << static_cast<const void*>(name) <<"\n";
std::cout << static_cast<const void*>(&name[0]) << "\n";
}
Possible output:
0x402005
0x402005
The static cast is needed to bybass the ostream::operator<< for char* that prints the string.
&name is the address of where name is stored, not the address stored in name.
This answer applies to both C and C++, with the exception of the paragraph that says "in C++".
why is &name not the same as &name[0]?
Because the address where the pointer is stored is separate from the address where the pointer points to, which is where the array is.
And that the address of an array is just the address of the first item in that array
You seem to be conflating arrays and pointers. An array is not a pointer and pointer is not an array. The quoted sentence is about arrays and it doesn't apply to pointers.
char *name = "Emma 123";
This is ill-formed in C++ (since C++11). String literal is not convertible to a pointer to non-const char. To fix this, use const char*.
printf("This is the pointer we get from name: %p\n", &name);
printf("This is the pointer we get by resolving &name: %p\n", &name);
The behaviour of this program is undefined. You must pass arguments of correct type, and the correct type for %p is void* while you passed char* and char**. A corrected example:
const void* v_name = name;
void* v_name_a = &name;
printf("This is the pointer we get from name: %p\n", v_name);
printf("This is the pointer we get by resolving &name: %p\n", &v_name_a);
This question already has answers here:
Does C have a string type? [closed]
(7 answers)
Closed 5 years ago.
Say that in a class student, I had written the following public member function:
char *p()
{ return (name);}
Now, name is actually a datamember(private section) and is a character string. I assume that this means char* can return a string. If I were writing something similar like:
void main()
{ char *s = "GOODLUCK";
cout<<*s;
}
What does *s give me here? I think it's the whole string 's'. Am I correct?
Description below is far from pedantic, but should help you to start digging into pointers:
char *s means, that s is pointer to char. In other words, it is variable, which can store address of area, capable of storing char. BTW I prefer writing char* s (space moved) as more descriptive: s is variable name, char* is variable type.
"GOODLUCK" is an array of 9 chars (the last one is '\0'). All array memebers are always kept one after another in memory, so if you know address of the first member, you can find address of the second, the third and so on. That's why arrays in C++ are handled as address of the first member.
s = "GOODLUCK"; means "store array address (aka address of the first element) into s". So s now points to the first char of "GOODLUCK".
*s means "get data, which variable points at". s points to the first char of string, so *s is simply a G
cout << *s; means "calculate *s and pass it to cout", so it's identical to cout <<'G';
writing cout << s; (note missing asterisk) doesn't pass one char to cout, but passes pointer to char. cout expects pointer to char to be passed only when it represents address of array, not address of single char. cout will print one by one all members of array, so the whole string will be displayed.
Bottom line: char *p() { return (name);} actually returns address of the first char of the name, but address of the first char represents the whole name. Possible further reading
#include<iostream.h>
#include<conio.h>
void print(char *str){
cout<<str;
}
int main(){
clrscr();
char str[]="abcdef";
print(&str);
getch();
return 0;
}
Error
1. Cannot convert 'char[7]' to 'char *'
2.Type mismatch in parameter 'str' in call to print(char *)
Since the parameter list of function print consists of a pointer, then passing &str in function call should be correct
Also if I remove the '&' the program runs fine (even though the print function requires a character reference).
Since the parameter list of function print consists of a pointer, then passing &str in function call should be correct
That's not exactly true: it is not sufficient to pass just any pointer, it needs to be of the correct type. &str is a pointer to an array, while you need a pointer to a single array element.
Since arrays in C++ "decay" to pointers when you pass them to functions, all you need to do is removing the ampersand:
print(str);
if I remove the & the program runs fine (even though the print function requires a character reference)
That's right! An array name (in this case, str) is implicitly converted to a pointer, which is equal to the pointer to array's initial element. In other words, it's the same as writing
print(&str[0]);
print(&str);
is wrong since the type of &str is char (*)[7] while the expected argument type is char*.
To illustrate the difference between the two types:
char str[]="abcdef";
char (*ptr1)[7] = &str; // Take the address of the array.
char* ptr2 = str; // Use the array variable. It decays to a pointer
*ptr2 = 'A'; // OK.
*ptr1 = 'A'; // Not OK.
(*ptr1)[0] = 'A'; // OK
Just pass str directly to print() like so:
// this already provides std::cout
#include<iostream.h>
// this is unnecessary
//#include<conio.h>
// you could do this to avoid std:: everywhere:
//using namespace std;
void print(char *str){
// don't forget the namespace:
std::cout<<str;
}
int main(){
clrscr();
char str [] = "abcdef";
// no "&", just pass str
print (str);
getch();
return 0;
}
Arrays in C/C++ are just pointers to the first element of the array.
http://www.cplusplus.com/forum/articles/9/
Function print is declared as having a parameter of type char *
void print(char *str){
cout<<str;
}
Within the main it is called with an argument of type char ( * )[7] because it is this type that expression &str has.
char str[]="abcdef";
//...
print(&str);
You should call the function simply like
print( str );
In this case the array is converted to pointer to its first character and expression str has type char *
When you have an array of type T as for example
T a[10];
then the array used in expressions is converted to pointer to its first element. For example this
T *ptr = a;
is a correct declaration.
On the other hand if you are using expression &a then the correct declaration for a pointer will look like
T ( *ptr )[10] = &a;
That is in this case ptr is a pointer to an object of type T[10]
And I advice to use a more modern compiler.:)
I am learning typecasting.
Here is my basic code, i dont know why after typecasting, when printing p0, it is not showing the same address of a
I know this is very basic.
#include <iostream>
using namespace std;
int main()
{
int a=1025;
cout<<a<<endl;
cout<<"Size of a in bytes is "<<sizeof(a)<<endl;
int *p;//pointer to an integer
p=&a; //p stores an address of a
cout<<p<<endl;//display address of a
cout<<&a<<endl;//displays address of a
cout<<*p<<endl;//display value where p points to. p stores an address of a and so it points to the value of a
char *p0;//pointer to character
p0=(char*)p;//typecasting
cout<<p0<<endl;
cout<<*p0;
return 0;
}
When you pass a char * pointer to the << operator of std::cout, it prints the string that the pointer points to, not the address. It's the same behavior as the following code:
const char *str = "Hello!";
cout << str; // Prints the string "Hello!", not the address of the string
In your case, p0 doesn't point to a string, which is why you're getting unexpected behavior.
The overload of operator<<, used with std::cout and char* as arguments, is expecting a null-terminated string. What you are feeding it with, instead, is a pointer to what was an int* instead. This leads to undefined behavior when trying to output the char* in cout<<p0<<endl;.
In C++, is often a bad idea to use C-style casts. If you had used static_cast for example, you would have been warned that the conversion your are trying to make does not make much sense. It is true that you could use reinterpret_cast instead, but what you should be asking yourself is: why am I doing this? Why am I trying to shoot myself in the foot?
If what you want is to convert the number to string, you should be using other techniques instead. If you just want to print out the address of the char* you should be using std::addressof:
std::cout << std::addressof(p0) << std::endl;
As others have said cout is interpreting the char* as a string, and not a pointer
If you wanted to prove that the address is the same whatever type of pointer it is then you can cast it to a void pointer
cout<<(void*)p0<<endl;
In fact you get the address for pretty much any type other than char&
cout<<(float*)p0<<endl;
To prove to yourself that a char* pointer would have the same value use printf
printf("%x", p0);
I am working in a program using the DWARF and ELF info. I am hooked to another program using a tool called Pin. I have the addresses from the global variables declared in "Y" program and I hook it into my Pin module which I will call "X".
I am getting a bunch of addresses for these global variables. Unfortunately I am having troubles when I try to dereference them. For example (right now I am doing things manually to see if it is doing what is supposed to be doing):
char * limit, * address1;
for(address1 = (char *) 0x804A040, limit = address1 + bytesize; address1 < limit; address1++)
cout << *(address1) << "\n";
I should be getting the variable that is stored in that address which is a char * to a word. Do I have to dereference two pointers in this case? The address and then the char * stored in that address?
This works perfectly fine when I want to dereference an int variable, but whenever I try to dereference a char pointer or variable I get non-ASCII values...
Think like this: if you want to dereference an int, you use int *:
int *addr = (int *)0x12345678;
printf("%d\n", *addr);
But a string is already a pointer, so if you do this:
char *addr = (char *)0x12345678;
You don't need to dereference it to print it out, so you get it this way:
printf("%s\n", addr);
Additionally, suppose you have this memory:
00000001: 0x12345678
...
12345678: 'A'
12345679: 'B'
1234567A: '\0'
...
Let's access the address 0x00000001 and see what we can do:
unsigned int *addr = (unsigned int *)0x00000001;
Now *addr holds an integer which is the address of the first character of our string. Functions that take a string argument, usually ask for the string address, that is, a pointer to it, so *addr is also the string we should print on cout or printf for example.
// This should print "AB"
printf("%s\n", (char *)(*addr));
Now if you dereference our value (0x12345678), we'd get the string's first character, and only it, as a char. So if you misuse it and dereference it to a char *, printf would try to search for the memory 'A', which is 0x00000041, and would probably get a segmentation fault.
So, the right way to dereference its value, to get the first character would be this:
// This should print "A"
printf("%c\n", (char)(**addr));
So, as a conclusion, if you are still getting non-ASCII values, that's probably an issue with this kind of hierarchy between addresses, and I would recommend you to strictly debug the memory and see if creating a pointer to a pointer is the right path to your string.
Yes, you need to dereference two pointers. First to get the address of the variable that holds the char*, and then to dereference the char*.