Understanding char * to int * conversion and its meaning - c++

I have the following simple piece of code,
unsigned long the_function(const char* p){
int* ip = (int*)p;
printf("%d\n",ip);
}
I know that the first line cast is meaning less but that the code given to me.
Now when i just pass "a" to the function i get the constant output
4196024
could someone explain to me what is the meaning.

It's printing the address of the string.

You're attempting to print the address of the pi pointer which is of type (int *). The address is represented with 8 bytes, but ints may be represented with 4 bytes, so when you attempt to print pi using %d only a portion of the pointer is printed. As Remy Lebeau pointed out using %p is the correct way to print a pointer address.
As an aside, you're converting the char * pointer to a type of int * but you never try to access the value of what int * is pointing at, in case that's what you were trying to do.

Related

Why does my pointer to a char only get the first character in it?

I initialized a char and a pointer, and then point it to the char. But I found that only the first character in the char was passed into the pointer. How could this be? Appreciate any advice!
char p[]="This is a long char.";
std::cout<<sizeof(p)<<"\n";
char *ptr=p;
std::cout<<*ptr<<"\n";
Got:
21
T
Program ended with exit code: 0
When checking the value of variables I noticed that:
ptr=(char *) "This is a long char."
*ptr=(char) 'T'
Why is the ptr holding the whole char but the content in it is only the first character? Isn't this the opposite of what we call a pointer? Got really confused...
When you said:
std::cout<<*ptr...
you dereferenced ptr, which gives you the (first) character that ptr is pointing to.
flyingCode's answer shows you how to print the entire string.
In C++, an array is just like multiple variables grouped together, so they each have a memory address, but they are one after another.
So, the pointer is pointing at the address of the first element, and the other elements are in the adresses right after that in order.
When you use the * operator on a pointer, it references the contents of the memory address the pointer is pointing to.
If you wanted to access another element of the array using this, you would use *(ptr + 5) to offset the memory address.
When you use the variable name alone, the language just does the offset for you and gets all the contents of the array. The pointer doesn't know the length of the array, but it can find the end of it, because char arrays always end with a null character (\0).
ran your code in repl and changing it to the code below worked :D
char p[]="This is a long char.";
std::cout<<sizeof(p)<<"\n";
char *ptr=p;
std::cout<<ptr<<"\n"; //notice no *
I recommend you use std::string rather than c-strings unless you have a specific need for them :)

How do these pointers point to more than just a char or a byte? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I'm a high school student, recently started my final exam project using Arduino, and I'm trying to understand this piece of code I found in an example sketch for a radio transmitter using VirtualWire.
const char *msg = "hello";
vw_send((byte *)msg, strlen(msg));
I was never taught pointers or even C at all, so I'm having some issues understanding how this works.
*msg is a pointer to char, right ? At that point, it should be null, so why can you assign a value to it ?
Also, what the holy hell is (byte *)msg ? What do these parentheses mean ? Is it a byte equal to the value at pointer msg ? How does that work considering it's a char? And why is it necessary ?
Full code for context:
// transmitter.pde
//
// Simple example of how to use VirtualWire to transmit messages
// Implements a simplex (one-way) transmitter with an TX-C1 module
//
// See VirtualWire.h for detailed API docs
// Author: Mike McCauley (mikem#airspayce.com)
// Copyright (C) 2008 Mike McCauley
// $Id: transmitter.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $
#include <VirtualWire.h>
void setup()
{
Serial.begin(9600); // Debugging only
Serial.println("setup");
// Initialise the IO and ISR
vw_set_ptt_inverted(true); // Required for DR3100
vw_setup(2000); // Bits per sec
}
void loop()
{
const char *msg = "hello";
digitalWrite(13, true); // Flash a light to show transmitting
vw_send((byte *)msg, strlen(msg));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(13, false);
delay(200);
}
At that point, it should be null, so why can you assign a value to it ?
No, it's not null.
Consider this:
int x = 42;
Would you expect x to have the value 0 or the value 42 ? I assume that you would answer 42
So why assume that
const char *msg = "hello";
will cause msg to be NULL? It won't.
Instead it is initialized so that it points to the string "hello". Or more precisely - it points to the char h in the string "hello".
Also notice that you can assign the pointer to point to some other char later on.
Example:
#include <stdio.h>
int main(void) {
const char* p = "hello"; // Now p points to the 'h' in "hello"
printf("%s\n", p);
p = "world"; // Now p points to the 'w' in "world"
printf("%s\n", p);
return 0;
}
Output:
hello
world
In other words - you can give the pointer a new value as many times as you like.
Here is another example:
#include <stdio.h>
int main(void) {
const char* p = "hello"; // Make p point to the first char in the string
do
{
printf("%s\n", p);
p = p + 1; // Make p point to the next char in the string
} while (*p);
return 0;
}
Output:
hello
ello
llo
lo
o
const char *msg = "hello" - creates a pointer to a char and points it at the first character of the string "hello". In C, there are no string types. The convention is to use a pointer to the first char of the string, and use a null terminator to denote the end of the string.
vw_send((byte *)msg, strlen(msg)) - let's break this down
vw_send() - a function that expects a pointer to a byte (byte *), and an int number of bytes to read from that memory location
(byte *)msg - casts a pointer to a char (char *) into a pointer to a byte (byte *)
strlen(msg) - returns the length of the string pointed to by msg
vw_send() reads some number of byte from the memory location pointed to by it's first argument. The number of bytes to read is given by the second argument. Since the second argument is the length of the string pointed to by msg, and a byte is the same size as a char, the effect is that vw_send() will read and do whatever it does with the string pointed to by msg.
Also, what the holy hell is (byte *)msg ? What do these parentheses
mean ? Is it a byte equal to the value at pointer msg ? How does that
work considering it's a char? And why is it necessary ?
That is a typecast: its purpose is to inform the compiler to take what follows "not as it is, but something different".
In this case, probably vw_send() expects, as first parameter, a pointer to byte instead of a pointer to char. You have instead a pointer to char, so you use a typecast to keep the compiler happy. Note that typecasting is not always so simple; in this case it is ok because char and byte are anyway very similar (if not the same) on many platforms.
*msg is a pointer to char, right ?
EDIT: As datafiddler points out: It is a pointer only in the declaration, so some people like to write "char* msg" instead of "char *msg". It's the same code but looks different. Even "char * msg" whould be allowed and identical for the compiler.
But beside from the declaration, or on it's own, it's a "dereferenced pointer to a char" -> a char. The context is relevant here.
At that point, it should be null, so why can you assign a value to it ?
it is initialized with the memory address of "hello" (or, as told, more precise the 'h' in hello)
C/C++ doesn't set the value of a local variable automatically (yet?!). (only globals)
So the programmer can/must set it explicitly to a desired value.
Also, what the holy hell is (byte *)msg ? What do these parentheses mean ? Is it a byte equal to the value at pointer msg ? How does that work considering it's a char? And why is it necessary ?
This is a cast this tells the compiler to treat whatever "msg" is pointing to (it was 'h' of "hallo") as a pointer who is pointing to a "byte".
To get low level:
In the memory the 'h' would look like 0x63 or 98 or 01100010 (search for ASCII table) computers know only bits and bytes, remember
you tell the code that this number should be used as a character which means 'b'.
The function vw_send dosn't care about characters it does care about "how many bits shall be sent in one chunk" so you can tell the function "please don't care that this is a pointer to char, take it as a pointer to some 8-bit values (called "byte") and send!"
I suspect the type byte may be a typedef (kind of renaming of types) to "unsigned char". This would be of the same size as char but the value may be interpreted different.
I suspect further this is to stop the compiler to complain about wrong types during the call of vw_send(byte *, int) or similar. You can do this if you know, that the called function can handle the data pointed to as another type. Kind of, casting is where the (black) magic happens...

difference between int* and char* in c++

#include <iostream>
using namespace std;
int main() {
int * a[5];
char * b[5];
cout<<a[1]; // this works and prints address being held by second element in the array
cout<<b[1]; // this gives run time error . why ?
return 0;
}
Can anyone please explain to me cout<<b[1] gives run-time error ?
Shouldn't both int and char array behave similar to each other ?
Because IOStreams are designed to treat char* specially.
char* usually points to a C-string, so IOStreams will just assume that they do and dereference them.
Yours don't.
As others have said, iostream formatted output operators consider char* to point to C-style string and attempt to access this string.
What others have not said so far, is that if you are interested in the pointer, you need to cast the pointer in question to void*. For example:
std::cout << static_cast<const void*>(buf[1]);
An output stream such as cout gives special consideration to char * that it does not give to other pointers. For pointers other than char *, it will simply print out the value of the pointer as a hexadecimal address. But for char *, it will try to print out the C-style (i.e. null terminated array of char) string referred to by the char *. Therefore it will try to dereference the char pointer, as #AlexD points in the comment to your post.
C++ (inheriting it from C) treats character pointers specially. When you try to print a[1] of type int* the address is printed. But when you try to print b[1] of type char* the iostream library - following the rest of the language - assumes that the pointer points to the first character of zero-terminated string of characters. Both your output statements are initialised behaviour, but in the case of char* crash is much more likely because the pointer is dereferenced.

How to: Typecasting Pointers on c++

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);

Dereferencing a char pointer in C/C++?

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*.