Since each single hexadecimal digit corresponds to 4 bits and each byte of memory requires 2 hexadecimal digit, Why the increment in the memory addresses in the code below is happening in the nibbles not the whole byte?
#include <iostream>
using namespace std;
int main()
{
int a , b, c, d;
cout << &a << "\t" << &b << "\t" << &c << "\t" << &d << endl;
cout << (long) &a << "\t" << (long)&b << "\t" << (long) &c << "\t" << (long)&d << endl;
return 0;
}
As you see in the output below the increment in memory addresses for our int type happened only in nibbles. For example the first increment is from 58 to 5c (4 nibbles from 8 to c) and 4 nibbles is only 2 bytes not 4.
output:
0x7ffdc94b6e58 0x7ffdc94b6e5c 0x7ffdc94b6e60 0x7ffdc94b6e64
140727980617304 140727980617308 140727980617312 140727980617316
140727980617304 140727980617308
As you can see, the difference between these two addresses is 4. Pointer addresses are, basically, memory addresses. These addresses are 4 bytes apart. Your ints take up four bytes long. Hence, consecutive ints, stored in memory, will be 4 addresses apart.
4 nibbles from 8 to c
You are conflating a term used to describe the representation of a single hexadecimal number with memory addresses.
"nybble" is to hexadecimal is as "digit" is to our natural base-10 number representation.
Whether each particular memory address is presented as a hexadecimal number, consisting of nybbles, or a decimal addresses consisting of digits, makes no difference whatsoever. The above two memory addresses differ by a value of 4, whether you choose to view them as hexadecimal nybbles or decimal digits. The memory addresses are 4 addresses apart. The End.
Related
#include <iostream>
using std::cout;
using std::endl;
int main(void) {
std::string fx = "6x^2+6x+4";
int part1 = fx[0] * fx[3];
cout << fx[0] << endl;
cout << fx[3] << endl;
cout << part1;
}
So I have this string and fx[0] and fx[3] are obviously integers: when I print them to the console they print out just fine; however, part1 (their multiplication) equals some totally unrelated number? Can anyone help?
Here is the output:
6
2
2700
Your fx[0] and fx[3] variables are of type char (which is an integer type in C++). However, the actual values in those two elements of your fx string will be representations of the digits, 6 and 2, not the numerical values of those digits.
Very often, those representations will be ASCII codes (but that's not required); however, what is required is that the representations of the digits 0 thru 9 have contiguous, sequential values. Thus, by subtracting the value of the digit, 0, we can convert to their numerical representations.
In your case, the following line will do the conversion:
int part1 = (fx[0]-'0') * (fx[3]-'0');
The reason why you see the correct values when printing fx[0] and fx[3] is because the version of the cout << operator that takes a char argument is designed to print the represented character (not its 'ASCII' code); however, the cout << operator for an int type (like your part1) will print the actual value represented internally. (Try changing one of your lines to cout << (int)fx[0] << endl; to see the difference.)
P.S. Don't forget the #include <string> header – some implementations do that implicity inside the <iostream> header, but don't rely on that!
well, first of all, string::operator[] returns a char... then, a char can be casted to an int, and the cast works checking the ID in the ASCII table (in your case)
In ASCII, the ID of "6" and "2" are respectively 54 and 52 (you can check it here for example)... so your program is taking the two char, casting them to int, and multiplying them (54 * 50 = 2700)
If you need to interpret those as the integer value they represent, you can check this answer:
int val = '6' - '0'; // val == 6
Characters are values representing glyphs from some representation, usually the ASCII table. The numeric value of a character is not the same as the glyph that is printed on the screen. To convert a numeric-looking char to an actual "0-based" numeric value, subtract '0' from your char value.
(fx[3]-'0']) will be the numeric value of character represented at position 3.
You are multiplying character types. so the characters '6' and '2' will converted to its integer values 54 and 50 respectively then multiplication is applied. This works based on C++ type conversion rule. Then you will get 2,700. Try the modified sample code
#include <iostream>
using std::cout;
using std::endl;
int main(void) {
std::string fx = "6x^2+6x+4";
int part1 = fx[0] * fx[3];
cout << fx[0] << endl;
cout << fx[3] << endl;
cout << part1;
cout << std::endl;
cout << (int)fx[0] << " " << (int)fx[3] << std::endl;
}
And the results
6
2
2700
54 50
This question already has answers here:
What does "dereferencing" a pointer mean?
(6 answers)
Closed 2 years ago.
I am new to C++, but I am curious enough to dig into these strange things.
I was wondering what happens when I convert a pointer to an int and realized could they indicate something. So I wrote this program to test my ideas as pointers in the same array are close enough in terms of memory location to be compared.
This is the code that will explain my question clearly.
#include <iostream>
using namespace std;
int main() {
cout << "--------------------[ Pointers ]--------------------" << endl;
const unsigned int NSTRINGS = 9;
string strArray[NSTRINGS] = { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" };
string *pStartArray = &strArray[0]; // Setting pStartArray pointer location to the first block of the array.
string *pEndArray = &strArray[NSTRINGS - 1]; // Setting pEndArray pointer location to the last block of the array.
cout << "---[ pStartArray value : " << *pStartArray << endl; // Showing the value of the pStartArray pointer (Just for safety check).
cout << "---[ pEndArray value : " << *pEndArray << endl; // Showing the value of the pEndArray pointer (Just for safety check).
short int blockDifferential = pEndArray - pStartArray; // Calculating the block differential of those two pointers.
cout << "---[ Differential of the block locations that pointers are pointing to in array (pEndArray - pStartArray) : " << blockDifferential << endl;
long long pStartIntLocation = (long long)pStartArray; // Converting the memory location (Hexadecimal) of pStartArray pointer to int (Maybe it's byte, regardless of being positive or negative). What's your opinion on this?
cout << "---[ (long long) pStartArray current memory location to int : \"" << pStartIntLocation << "\"" << endl;
long long pEndIntLocation = (long long)pEndArray;
cout << "---[ (long long) pEndArray current memory location converted to int : \"" << pEndIntLocation << "\"" << endl; // Converting the memory location (Hexadecimal) of pEndArray pointer to int (Maybe it's byte, regardless of being positive or negative). What's your opinion on this?
short int locationDifferential = pEndIntLocation - pStartIntLocation; // And subtracting the integer convetred location of pEndArray from pStartArray.
cout << "---[ Differential of the memory locations converted to int ((long long)pStartArray - (long long)pEndArray) : " << locationDifferential << " (Bytes?)" << endl; // Seems like even after running the program multiple times, this number does not change. Something's fishy. Doesn't it seem like it's a random thing. It must be investigated.
cout << "---[ Size of variable <string> (According to the computer that it's running) : " << sizeof(string) << " (Bytes)" << endl; // To know how much memory does a string consume. For example mine was 40.
// Here it goes interesting. I can get the block differential of the pointers using <locationDifferential>.
cout << "---[ Differential of the cell location (AGAIN) using the <locationDifferential> that I have calculated : " << locationDifferential/sizeof(string) << endl; // So definately <locationDifferential> was in bytes. Because I got 8 again. I just wonder is it a new discovery. LOL.
/*
I might look really crazy, because I can't tell it another way. It just can't happen.
This is the last try to make it as clear as I can.
pStrArray ]--\ pEndArray ]--\
\ - 8 cell difference - \
Array = | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|-------- Differential ---------|
Cell difference : 8 string cells
String size that I considered : 32 Bytes
data (location difference) : 8 * 32 = 256
So if you see this, all this might make sense.
I am excited to see what opinions you professional programmers have come up with.
- D3F4U1T
*/
cout << "----------------------------------------------------" << endl;
return 0;
}
How does this exactly work?
pStartIntLocation, pEndIntLocation are all in bytes?
If so, why sometimes they return negative value?
This is strange.
Also correct me if I am wrong about any information I provided.
- Best regards.
- D3F4U1T.
Edit 2:
Does the value that results from the conversion from pointer to a long long mean anything? Like the memory address but with the difference that this one is in bytes?
Edit 3: Seems like this is related to virtual address space. Correct me if I am wrong. Does the OS have any mechanism to number the memory as bytes. For example: Byte 1 , Byte 2 , ....
A "pointer" is an integer quantity of some length whose contents are understood to represent a memory address. (By convention, zero means NULL ... no address.)
If you typecast it into an integer, you are simply declaring to the compiler that *"no, these however-many bits should not be treated as an address ... treat them as an integer." The content of the location does not change, only the compiler's interpretation of it.
Typecasting does not change the bits – only the momentary interpretation of what they are and what they mean.
FYI: unions are another way to do a similar thing: every element of a union overlaps the others and describes various interpretations of the same area of storage. (In the Fortran language, this was called EQUIVALENCE.)
I have the following exercise:
Implement a function void float to bits(float x) which prints the bit
representation of x. Hint: Casting a float to an int truncates the
fractional part, but no information is lost casting a float pointer to
an int pointer.
Now, I know that a float is represented by a sign-bit, some bits for its mantissa, some bits for the basis and some bits for the exponent. It depends on my system how many bits are used.
The problem we are facing here is that our number basically has two parts. Let's consider 8.7 the bit representation of this number would be (to my understanding) the following: 1000.0111
Now, float's are stored wit a leading zero, so 8.8 would become 0.88*10^1
So I somehow have to get all the information out of my memory. I don't really see how I should do that. What should that hint hint me to? What's the difference between a integer pointer and a float pointer?
Currently I have this:
void float_to_bits() {
float a = 4.2345678f;
int* b;
b = (int*)(&a);
*b = a;
std::cout << *(b) << "\n";
}
But I really don't get the bigger picture behind the hint here. How do I get the mantissa, the exponent, the sign and the basis? I also tried playing around with the bit-wise operators >>, <<. But I just don't see how this should help me here, since they won't change the pointers position. It's useful to get e.g. the bit representation of an integer but that's about it, no idea what use it'd be here.
The hint your teacher gave is misleading: casting pointer between different types is at best implementation defined. However, memcpy(...)ing an object to a suutably sized array if unsigned char is defined. The content if the resulting array can then be decomposed into bits. Here is a quick hack to represent the bits using hexadecimal values:
#include <iostream>
#include <iomanip>
#include <cstring>
int main() {
float f = 8.7;
unsigned char bytes[sizeof(float)];
std::memcpy(bytes, &f, sizeof(float));
std::cout << std::hex << std::setfill(‘0’);
for (int b: bytes) {
std::cout << std::setw(2) << b;
}
std::cout << ‘\n’;
}
Note that IEEE 754 binary floating points do not store the full significand (the standard doesn’t use mantissa as a term) except for denormalized values: the 32 bit floats store
1 bit for the sign
8 bits for the exponent
23 bits for the normalized significand with the non-zero high bit being implied
The hint directs you how to pass the Float into an Integer without passing through value conversion.
When you assign floating-point value to an integer, the processor removes the fraction part. int i = (int) 4.502f; will result in i=4;
but when you make a int pointer (int*) point to a float's location,
no conversion is made, also when you read the int* value.
to show the representation, i like seeing HEX numbers,
thats why my first example was given in HEX
(each Hexa-decimal digit represents 4 binary digits).
but it is also possible to print as binary,
and there are many ways (I like this one best!)
Follows an annotated example code:
Also available # Culio
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
float a = 4.2345678f; // allocate space for a float. Call it 'a' and put the floating point value of `4.2345678f` in it.
unsigned int* b; // allocate a space for a pointer (address), call the space b, (hint to compiler, this will point to integer number)
b = (unsigned int*)(&a); // GREAT, exactly what you needed! take the float 'a', get it's address '&'.
// by default, it is an address pointing at float (float*) , so you correctly cast it to (int*).
// Bottom line: Set 'b' to the address of a, but treat this address of an int!
// The Hint implied that this wont cause type conversion:
// int someInt = a; // would cause `someInt = 4` same is your line below:
// *b = a; // <<<< this was your error.
// 1st thing, it aint required, as 'b' already pointing to `a` address, hence has it's value.
// 2nd by this, you set the value pointed by `b` to 'a' (including conversion to int = 4);
// the value in 'a' actually changes too by this instruction.
cout << a << " in binary " << bitset<32>(*b) << endl;
cout << "Sign " << bitset<1>(*b >> 31) << endl; // 1 bit (31)
cout << "Exp " << bitset<8>(*b >> 23) << endl; // 8 bits (23-30)
cout << "Mantisa " << bitset<23>(*b) << endl; // 23 bits (0-22)
}
While I was writing code on a 64 bit machine for a c++ program,I noticed that printing the address of a variable (for example) returns just 12 hexadecimal characters, instead of 16. Here's an example code:
int a = 3 ;
cout sizeof(&a) << " bytes" << endl ;
cout << &a << endl ;
The output is:
8 bytes
0x7fff007bcce0
Obviously, the address of a variable is 8 byte (64 bit system). But when I print it, I get only 12 hexadecimal digits instead of 16.
Why this? I think that is due to the fact that the 4 "lost" digits
were leading zeroes, that were not printed. But this is only my
thought, and I wish to have a definitive and technically correct
answer.
How could I print the entire address? Is there a built-in solution,
or should I manually use "sizeof" in order to get the real lenght and
then add to the address the right number of zeroes?
Forgive me, I googled for a day for an answer to my stupid question, but I wasn't able to find an answer. I'm just a newbie.
(On stackoverflow I did not find any question/answer about what I needed to know, but maybe I'm wrong.)
Someone asks a pretty similar question here: c++ pointer on 64 bit machine
Hope this helps :)
To print the full 64bit address with leading zeros you can use:
std::cout
<< "0x"
<< std::hex
<< std::noshowbase
<< std::setw(16)
<< std::setfill('0')
<< n
<< std::endl ;
Got it from: How can I pad an int with leading zeros when using cout << operator?
I am currently writing a book on C++ and windows 32-bit programming for peeps such as you, but unfortunately I am not yet done with it :(
The following code demonstrates how you would display a 64-bit unsigned number using cout method:
// Define a 64-bit number. You may need to include <stdint.h> header file depending on your C++ compiler.
uint64_t UI64 = 281474976709632ULL; // Must include ULL suffix and this is C99 C++ compiler specific.
// unsigned __int64 UI64 = 281474976709632ULL; // Must include ULL suffix and this is Microsoft C++ compiler specific.
// Set decimal output.
cout << dec;
// Display message to user.
cout << "64-bit unsigned integer value in decimal is: " << UI64 << endl;
cout << "\n64-bit unsigned integer value in hexadecimal is: ";
// Set the uppercase flag to display hex value in capital letters.
cout << uppercase;
// Set hexadecimal output.
cout << hex;
// Set the width output to be 16 digits.
cout.width(16);
// Set the fill output to be zeros.
cout.fill('0');
// Set right justification for output.
right(cout);
// Display the 64-bit number.
cout << UI64 << endl;
You may need to (type) cast the address into a 64-bit unsigned value.
In this case, you can do the following:
// (type) cast pointer adddress into an unsigned 64-bit integer.
uint64_t UADD64 = (uint64_t)&UI64; // C99 C++ compiler specific.
I have the following declaration
char c[] = "Hello";
string c2 = "Hello";
I want to compare a) how many bytes of memory both need and b) the character lengths.
I know the character arrays add a null terminator at the end of the string where as string data types don't.
Using
cout << "The sizeof of c: " << sizeof(c);
cout << "The sizeof of c2: " << sizeof(c2);
returns 6 and 4 and I'm not sure why 4 and not 5?
also how does length function compare here ...
When I use the following code
cout << "The sizeof of c: " << sizeof(c);
cout <<"The sizeof of c2: " << c2.length();
I get 6 and 5 ... but is it comparing the lengths the same way?
Thanks.
a) how many bites of memory both need and
You correctly used the sizeof operator that to determine how many bytes the character array occupies.
It is
sizeof( c )
As for the object of type std::string then it occupies two extents of memory. The first one is used to allocate the object itself and the second one is used to allocate the string the object holds.
So
sizeof( c2 )
will give you the size of the memory occupied by the object.
c2.capacity()
will give you the size that the object allocated to store the string and maybe some additional characters that will be filled in future.
When I use the following code cout << "The sizeof of c: " <<
sizeof(c); cout <<"The sizeof of c2: " << c2.length();
I get 6 and 5
If you want to compare the strings itself without the terminating zero that the character array has then you should write
cout << "The length of c: " << std::strlen(c);
cout <<"The length of c2: " << c2.length();
and you will get result 5 and 5.
You could make the following experiment with objects of type std::string.
std::string s;
std::cout << sizeof( s ) << '\t' << s.capacity() << '\t' << s.length() << std::endl;
std::string s1( 1, 'A' );
std::cout << sizeof( s1 ) << '\t' << s1.capacity() << '\t' << s1.length() << std::endl;
std::string s3( 2, 'A' );
std::cout << sizeof( s2 ) << '\t' << s2.capacity() << '\t' << s2.length() << std::endl;
std::string s3( 16, 'A' );
std::cout << sizeof( s3 ) << '\t' << s3.capacity() << '\t' << s3.length() << std::endl;
sizeof(c) is the size of the array, which contains the five characters in the literal you initialise it with, plus a zero-valued terminator at the end, giving a total of six bytes.
sizeof(c2) is the size of the string class, which doesn't tell you anything particularly useful. The class manages a dynamically allocated memory containing the string's characters; that's not part of the string object itself.
c2.length() is the number of characters in the string managed by c2; five characters.
a) how many bytes of memory both need, and b) the character lengths
variable 'c' uses 6 bytes on stack (the 5 letters and the null terminator)
sizeof(c) = 6, strlen(c) = 5
Total bytes of memory needed: 6
if 'c' had 1000 chars,
sizeof(c) = 1001, strlen(c) = 1000)
Total bytes of memory needed: 1001
variable 'c2' uses 4 bytes on stack (I suspect a pointer, but have not confirmed),
and at least 5 bytes somewhere else (I think heap).
sizeof(c2) = 4, c2.size() = 5, strlen(c2.c_str()) = 5
Total bytes of memory needed: 9+ (4 + 5)+
if 'c2' had 1000 chars, i.e. c2.size() == 1000
4 bytes on the stack, and
at least 1000 bytes somewhere else (depending on implementation, probably a few more)
Total bytes of memory needed: 1004+
NOTE: std::string is a container. I think such values are not specified,
and should be considered implementation dependent.
I guess the size of the [] includes the terminating null character, thus 5+1=6 bytes.
The size of the string object returns 4 bytes which probably is the size of the pointer which points to the string object. 32 bits.
In the last case you're using the Length which is programmed to count the number of characters.
Well the size of c[] = "Hello" is 6 because the char array needs to allocate 1 more byte of
memory for the null \0 character.
the length() function returns the number of characters in the string literal.It does not include the null \0 character while counting.
std::string, like std::unique_ptr, std::shared_ptr, and std::vector, is a smart pointer plus some extra manipulation member functions.
When you pass one to sizeof, you're measuring the size of the smart pointer -- sizeof (std::string), not the content.