When I run the following code:
int i[] = {1,2,3};
int* pointer = i;
cout << i << endl;
char c[] = {'a','b','c','\0'};
char* ptr = c;
cout << ptr << endl;
I get this output:
0x28ff1c
abc
Why does the int pointer return the address while the char pointer returns the actual content of the array?
This is due to overload of << operator. For char * it interprets it as null terminated C string. For int pointer, you just get the address.
The operator
cout <<
is overload 'char *' so it knows how to handle it (in this case, printing all chars till the end one).
But for int is not, so it just prints out the 'memory address'
A pointer to char is the same type as a string literal. So for the sake of simplicity, cout will print the content of the char array as if it was a string. So when you are doing this:
cout << "Some text" << endl;
It does not print the address, the same way as your code is doing.
If you want to pring the address, cast it to size_t
cout << reinterpret_cast<size_t>(ptr) << endl;
I am learning pointer and this is my code. I defined a pointer to char (string actually) *str and a pointer to int *a, they are defined in the same way. I thought both str and a should be an address, but when I tried to output str and &str, a and &a, I found str is not an address, it is the string. What is the difference between char *str and int *a in terms of the type of str and a? Thank you.
#include<iostream>
#include<string>
using namespace std;
int main()
{
char *str = "FA";
cout << "str: " << str << endl;
cout << "&str: " << &str << endl;
int b = 5;
int *a = &b;
cout << "a: " << a << endl;
cout << "&a: " << &a << endl;
}
this is output:
str: FA
&str: 0x7fff5a627280
a: 0x7fff5a62727c
&a: 0x7fff5a627288
Well, this comes down to C semantics. A string is not a type defined in C. char is the type of a single character. In order to handle strings in C, by convention a pointer to char means a string that starts at the position this pointer points to and ends at the first 0 byte.
To make that clear:
char *str = "ABC";
"translates" to something like
const char <nosymbol>[4] = {'A', 'B', 'C', '\0'};
char *str = &(<nosymbol>[0]);
C++ knows about this special meaning of a char * and so, the << operator will, following the principle of least surprise for C programmers, take char * as a string.
The << operator for streams has an overload for char * that outputs a C-style string. This is usually what you want, but if it's not what you want, you can use reinterpret_cast<void*> or addressof.
Consider the following example
I want to print the address of "hello", not of ptr
#include<iostream>
using namespace std;
int main()
{
char *ptr = "HELLO";
cout<<"VALUE OF ptr"<<ptr;
cout<<"ADDRESS OF ptr"<<&ptr;
cout<<"WANT TO PRINT ADDRESS OF STRING HELLO";
return 0;
}
The << operator for most types prints the value of the right operand. The << operator for char* is different in that it prints the string that the char* value points to; it dereferences the pointer, and then traverses the characters of the string, printing each one, until it reaches the terminating '\0' null character.
To print the pointer value rather than what it points to, just convert it to void*, since << for void* prints the actual pointer value:
cout << "The address of the string is " << (void*)ptr << "\n";
or, if you prefer:
cout << "The address of the string is " << static_cast<void*>(ptr) << "\n";
(Incidentally, ptr should be a const char* rather than a char*.
Cast it to any other pointer. (void*)ptr or reinterpret_cast<int*>(ptr) or something.
I have this code:
int main()
{
char ch[15];
cout<<strlen(ch)<<endl; //7
cout<<sizeof(ch)<<endl; //15
return 0;
}
Why does strlen(ch) give different result even if it is empty char array?
Your code has undefined behavior because you are reading the uninitialized values of your array with strlen. If you want a determinate result from strlen you must initialize (or assign to) your array.
E.g.
char ch[15] = "Hello, world!";
or
char ch[15] = {};
sizeof will give the size of its operand, as the size of char is one by definition the size of a char[15] will always be 15.
strlen gives the length of a null terminated string which is the offset of the first char with value 0 in a given char array. For a call to strlen to be valid, the argument to must actually point to a null terminated string.
ch is a local variable and local variables are not initialized. So your assumption that it is an empty string is not correct. Its filled with junk. It was just a co-incidence that a \0 character was found after 7 junk characters and hence strlen returned 7.
You can do something like these to ensure an empty string-
char ch[15]={0};
ch[0]='\0`;
strcpy(ch,"");
Here's a similar thread for more reading
Variable initialization in C++
The problem is in
strlen(ch);
strlen counts the number of chars, untill hitting the \0 symbol. Here, ch is non-initialized, so strlen could return anything.
As for the result from strlen, in your case you have an uninitialized char array, and so strlen only happens to yield 7: there must be a null character at array element 8, but this code could give different results for strlen every time.
Always initialize strings, it's easy enough with an array: char str[15] = {0};
sizeof is an operator used to get the size of a variable or a data type, or the number of bytes occupied by an array, not the length of a C string; don't expect strlen and strcpy to be interchangeable, or even comparable in any useful way.
For instance:
int main()
{
char str[15] = "only 13 chars";
cout << "strlen: " << strlen(str) << endl;
cout << "sizeof: " << sizeof(str) << endl;
}
The output is:
strlen: 13
sizeof: 15
Returns the length of str.
The length of a C string is determined by the terminating
null-character: A C string is as long as the amount of characters
between the beginning of the string and the terminating null
character.
sizeof returns number of bytes (15). Your array is filled by garbage, so, strlen can returns any number. Correct example is
int main()
{
char ch[15] = {0};
cout<<strlen(ch)<<endl; //0
cout<<sizeof(ch)<<endl; //15
return 0;
}
The difference between sizeof and strlen in C++:
1) sizeof is a operator, strlen is a function;
2) The return type of sizeof is size_t,and it is defined (typedef) as unsigned int in its header; It gets the byte size of the memory allocation which can maximize to accommodate this object to be created in memory;
3) sizeof can use type as a parameter, while strlen can only use char pointer (char*) as a pointer, and it must be ended as '\0';
sizeof can also use function as a parameter, for instance:
short f() {return 100;}
std::cout << "sizeof(f()): " << sizeof(f()) << std::endl;
//The result will be sizeof(short), which is 2.
4) If char array is a parameter, it will not be degraded by sizeof, while strlen will degrade it as a char pointer;
5) The result of strlen will be calculated in the run time, not compilation time, strlen is used to get the real size of the content of a string (string, char array, char pointer) until the '\0', not the real size of memory allocation. Most of the compiler will calculate the result of sizeof in the compilation time, no matter the parameter is type or variable, that is why sizeof(x) can be used to decide the dimension of an array:
char str[20]="0123456789";
int a=strlen(str); //a=10;
int b=sizeof(str); //while b=20;
7) If the parameter of sizeof is a type, then parentheses are mandatory, while if the parameter is a variable, parentheses are optional, because sizeof is an operator not a function;
8) When you use a structured type or variable as a parameter, sizeof will return its real size, when you use a static array, sizeof will return the array size. But sizeof operator cannot return the size of an array which is created dynamically or externally. Because sizeof is a compilation time operator.
Here is an example of sizeof and strlen:
#include <iostream>
#include <cstdlib>
#include <string>
#include <cstring>
short f1 ()
{
return 100;
}
int f2 ()
{
return 1000;
}
int main()
{
char* char_star = "0123456789";
// char_star is a char pointer, sizeof will return the pointer size allocated in memory: depends on your machine
std::cout << "sizeof(char_star):" << sizeof(char_star) << std::endl;
// *char_star is the first element of the string, it is a char, sizeof will return the char size allocated in memory: depends on your machine, normally is 1
std::cout << "sizeof(*char_star):" << sizeof(*char_star) << std::endl;
// char_star is a char pointer, strlen will return the real size of the string until '\0': 10
std::cout << "strlen(char_star):" << strlen(char_star) << std::endl;
std::cout << std::endl;
char char_array[] = "0123456789";
// char_array is a char array, sizeof will return the array size allocated in memory, with a '\0' at the end: 10 + 1
std::cout << "sizeof(char_array):" << sizeof(char_array) << std::endl;
// *char_array is the first element of the array, it is a char, sizeof will return the char size allocated in memory: depends on your machine, normally is 1
std::cout << "sizeof(*char_array):" << sizeof(*char_array) << std::endl;
// char_array is a char array, strlen will return the real size of the string until '\0': 10
std::cout << "strlen(char_array):" << strlen(char_array) << std::endl;
std::cout << std::endl;
char_array_fixed[100] = "0123456789";
// char_array_fixed is a char array with fixed size, sizeof will return the array size allocated in memory: 100
std::cout << "sizeof(char_array_fixed):" << sizeof(char_array_fixed) << std::endl;
// *char_array_fixed is the first element of the array, it is a char, sizeof will return the char size allocated in memory: depends on your machine, normally is 1
std::cout << "sizeof(*char_array_fixed):" << sizeof(*char_array_fixed) << std::endl;
// *char_array_fixed is a char array with fixed size, strlen will return the real content size of the string until '\0': 10
std::cout << "strlen(char_array_fixed):" << strlen(char_array_fixed) << std::endl;
std::cout << std::endl;
int int_array[100] = {0,1,2,3,4,5,6,7,8,9};
// int_array is a int array with fixed size, sizeof will return the array size allocated in memory: 100
std::cout << "sizeof(int_array):" << sizeof(int_array) << std::endl;
// *int_array is the first element of the array, it is an int, sizeof will return the int size allocated in memory: depends on your machine, normally is 4
std::cout << "sizeof(*int_array):" << sizeof(*int_array) << std::endl;
// int_array is a int array with fixed size, strlen will throw exception
//std::cout << "strlen(int_array):" << strlen(int_array) << std::endl;
std::cout << std::endl;
char char_array2[] = {'a', 'b', '3'};
// char_array2 is a char array, sizeof will return the array size allocated in memory: 3
std::cout << "sizeof(char_array2):" << sizeof(char_array2) << std::endl;
// *char_array2 is the first element of the array, it is a char, sizeof will return the char size allocated in memory: depends on your machine, normally is 1
std::cout << "sizeof(*char_array2):" << sizeof(*char_array2) << std::endl;
// *char_array2 is a char array, strlen will return the real content size of the string until '\0': 3
std::cout << "strlen(char_array2):" << strlen(char_array2) << std::endl;
std::cout << std::endl;
char char_array3[] = {"abc"};
// char_array3 is a char array, sizeof will return the array size allocated in memory, with a '\0' at the end : 3 + 1
std::cout << "sizeof(char_array3):" << sizeof(char_array3) << std::endl;
// *char_array3 is the first element of the array, it is a char, sizeof will return the char size allocated in memory: depends on your machine, normally is 1
std::cout << "sizeof(*char_array3):" << sizeof(*char_array3) << std::endl;
// *char_array3 is a char array, strlen will return the real content size of the string until '\0': 3
std::cout << "strlen(char_array3):" << strlen(char_array3) << std::endl;
std::cout << std::endl;
std::string str = {'a', 'b', '3', '\0', 'X'};
// str is a string, sizeof will return the string size allocated in memory (string is a wrapper, can be considered as a special structure with a pointer to the real content): depends on your machine, normally is 32
std::cout << "str:" << str << std::endl;
std::cout << "sizeof(str):" << sizeof(str) << std::endl;
// *str means nothing, sizeof will throw exeption
//std::cout << "sizeof(*str):" << sizeof(*str) << std::endl;
// str is a string, strlen will return the real content size of the string until '\0': 3
std::cout << "strlen(str):" << strlen(str.c_str()) << std::endl;
std::cout << std::endl;
// sizeof is an operation, if the parameter is a type, parentheses are mandatory
std::cout << "sizof(int):" << sizeof(int) << std::endl;
// sizeof is an operation, if the parameter is a variable, parentheses are optional
std::cout << "sizof char_star:" << sizeof char_star << std::endl;
std::cout << "sizof char_array:" << sizeof char_array << std::endl;
// sizeof is an operation, can take a function as parameter
std::cout << "sizeof(f()): " << sizeof(f1()) << std::endl;
std::cout << "sizeof(f()): " << sizeof(f2()) << std::endl;
}
I have the following program which is giving run time error:
*The instruction at "x" referenced memory at "y"
The memory could not be written.*
Code:
int main() {
char *str1 = "Rain";
char *&str2 = str1;
cout << str1 << str2 << endl;
*str1 = 'M';
cout << str1 << str2 << endl;
//Here the error happens
*str2 = 'P';
cout << str1 << str2 << endl;
return 0;
}
What is the cause of this error.
The problem is that a string literal is technically a 'char const pointer'. Reading right to left a pointer to unmodifiable characters. Because of backward comparability with 'C' this can be auto cast to 'char pointer' by the compiler. This does not mean that the underlying type has changed and thus modifying the underlying const object is undefined behavior.
char *str1 = "Rain"; // Lie this is not a char*
char const* str9 = "Rain"; // This is the real type.
// String lieterals => "XXXXX" are char const*
If you want to modify the string what you need to do is declare an array.
char str6[] = "Rain";
str6[0] = 'M';
*str6 = 'P';