C++ strlen(ch) and sizeof(ch) strlen - c++

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

Related

size and the type of object created by the vector string constuctor in C++

int numRows = 5;
string s ="hellohi";
vector<string> rows(min(numRows, int(s.size())));
I think it is using the fill constructor. https://www.cplusplus.com/reference/vector/vector/vector/
but I don't know it creates a vector of NULL string or a vector of an empty string ?
And what is the size of the NULL ?
And what is the size of the empty string? 1 bytes ("/0"char) ?
The constructor you're using will create empty strings. For example you can check with:
// check the number of entries in rows, should be 5
std::cout << rows.size() << std::endl;
// check the number of characters in first string, should be 0
std::cout << rows[0].size() << std::endl;
// now the size should be 11, since there are 11 entries
rows[0] = "hello world";
std::cout << rows[0].size() << std::endl;
I believe the size of NULL is implementation defined, you could find it with:
std::cout << sizeof(nullptr) << std::endl;
I get 8 as the size (which is 64 bits)
Similar to the nullptr, the size of an empty string is probably also implementation defined, you can find it like:
std::string test_string;
std::cout << sizeof(test_string) << "\n";
std::cout << test_string.size() << "\n"; // should be 0 since the string is empty
test_string = "hello world"; // it doesn't matter how long the string is, it's the same size
std::cout << sizeof(test_string) << "\n";
std::cout << test_string.size() << "\n"; // should be 11 since the string has data now
I get 32 bytes for the size. The reason the size of the string doesn't change is due to how it works behind the scenes, instead of storing data (most of the time) it only stores a pointer to the data (which is always a fixed size).

What's the behaviour of "" + number and why it compile?

The code successfully compiles it but I can't understand why, for certain values of number, the program crashes and for other values it doesn't. Could someone explain the behavior of adding a long int with a char* that the compiler uses?
#include <iostream>
int main()
{
long int number=255;
std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
number=15155;
std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
return 0;
}
Test results:
Value 1 : >
Value 2 : Segmentation fault
Note: I'm not looking for a solution on how to add a string with a number.
In C++, "" is a const char[1] array, which decays into a const char* pointer to the first element of the array (in this case, the string literal's '\0' nul terminator).
Adding an integer to a pointer performs pointer arithmetic, which will advance the memory address in the pointer by the specified number of elements of the type the pointer is declared as (in this case, char).
So, in your example, ... << ("" + number) << ... is equivalent to ... << &""[number] << ..., or more generically:
const char *ptr = &""[0];
ptr = reinterpret_cast<const char*>(
reinterpret_cast<const uintptr_t>(ptr)
+ (number * sizeof(char))
);
... << ptr << ...
Which means you are going out of bounds of the array when number is any value other than 0, thus your code has undefined behavior and anything could happen when operator<< tries to dereference the invalid pointer you give it.
Unlike in many scripting languages, ("" + number) is not the correct way to convert an integer to a string in C++. You need to use an explicit conversion function instead, such as std::to_string(), eg:
#include <iostream>
#include <string>
int main()
{
long int number = 255;
std::cout << "Value 1 : " << std::flush << std::to_string(number) << std::flush << std::endl;
number = 15155;
std::cout << "Value 2 : " << std::flush << std::to_string(number) << std::flush << std::endl;
return 0;
}
Or, you can simply let std::ostream::operator<< handle that conversion for you, eg:
#include <iostream>
int main()
{
long int number = 255;
std::cout<< "Value 1 : " << std::flush << number << std::flush << std::endl;
number = 15155;
std::cout<< "Value 2 : " << std::flush << number << std::flush << std::endl;
return 0;
}
Pointer arithmetic is the culprit.
A const char* is accepted by operator<<, but will not point to a valid memory address in your example.
If you switch on -Wall, you will see a compiler warning about that:
main.cpp: In function 'int main()':
main.cpp:6:59: warning: array subscript 255 is outside array bounds of 'const char [1]' [-Warray-bounds]
6 | std::cout<< "Value 1 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
main.cpp:8:59: warning: array subscript 15155 is outside array bounds of 'const char [1]' [-Warray-bounds]
8 | std::cout<< "Value 2 : " << std::flush << ("" + number) << std::flush << std::endl;
| ^
Value 1 : q
Live Demo

Sizeof operator on string array is giving different output in C++

I am trying to compile the following code:
#include <iostream>
using namespace std;
void show1(string text1[]) {
cout << "Size of array text1 in show1: " << sizeof(text1) << endl;
}
int main() {
string text1[] = {"apple","melon","pineapple"};
cout << "Size of array text1: " << sizeof(text1) << endl;
cout << "Size of string in the compiler: " << sizeof(string) << endl;
show1(text1);
return 0;
}
And the output is shown below:
Size of array text1: 96
Size of string in the compiler: 32
Size of array text1 in show1: 8
I am not able to understand, why is the sizeof operator working on the same array giving two different outputs at two different points? Please explain.
The sizeof() operator returns the compile time size of the objects. It means that if your type allocates a memory chunk at run time from heap, that memory is not taken into account by sizeof().
For your first case, i.e.
string text1[] = {"apple","melon","pineapple"};
You have an array of 3 strings, so sizeof should return 3*sizeof(std::string). (3*32 = 96 in your case)
For your second case:
sizeof(string)
It should simply print the size of an string. (32 in your case).
Finally for your last case, do not forget that arrays are passed using a pointer in C/C++. So, your parameter is simply a pointer and sizeof() should print the size of a pointer on your machine.
Edit: As #ThomasMatthews has mentioned in the comments, if you are interested in getting the real size of an string (i.e. the number of characters inside it), you can use std::string::length() or std::string::size().
Try with member function 'size'.
Write this code:
#include <iostream>
using namespace std;
void show1(string text1[])
{
cout << "Size of array text1 in show1: " << text1->size() << endl;
}
int main()
{
string text1[] = {"apple","melon","pineapple"};
cout << "Size of array text1: " << text1->size() << endl;
cout << "Size of string in the compiler: " << sizeof(string) << endl;
show1(text1);
return 0;
}
Description:
std::vector has a member function size(). And std::string too. In std::vector return size of vector(all elements). In std::string returns all elements in array.

C++ Function Return Issue [duplicate]

This question already has answers here:
getting size of array from pointer c++
(6 answers)
Closed 3 years ago.
I am trying to make a function that can return the size of an array that can be different data types. I believe the expression (sizeof(z)/sizeof(*z))) returns the memory allocated to z divided by the memory size of the data type. The following code is my attempt to overload the function and return the size of the array as an integer. When I run the expression in the main function it works, but when I try to pass the array to the function I do not get the correct values and not sure what I am doing wrong. 68 / 4 = 17 which is the correct size of the array.
(1) outputs sizeof(z) and sizeof(*z) in the size function
(2) expression in main function
(3) outputs sizeof(z) in the main function
(4) outputs sizeof(*z) in the main function
#include <iostream>
using namespace std;
//
int size(int *data){
cout << sizeof(data) << ", " << sizeof(*data) << ", ";
return((sizeof(data))/(sizeof(*data)));
}
int size(char *x){return(sizeof(x)/sizeof(*x));}
int size(float *x){return(sizeof(x)/sizeof(*x));}
int size(double *x){return(sizeof(x)/sizeof(*x));}
int size(short int *x){return(sizeof(x)/sizeof(*x));}
int size(long int *x){return(sizeof(x)/sizeof(*x));}
int main(){
double x[9];
int z[17];
char k[29];
cout << "(1) Size : " << size(z) << endl;
cout << "(2) Size : " << (sizeof(z)/sizeof(*z)) << endl;
cout << "(3) Size : " << sizeof(z) << endl;
cout << "(4) Size : " << sizeof(*z) << endl;
cout << "(5) Size : " << size(z) << endl;
cout << "(6) Size : " << size(k) << endl;
return 0;
}
Terminal Output:
(1) Size : 8, 4, 2
(2) Size : 17
(3) Size : 68
(4) Size : 4
(5) Size : 8, 4, 2
(6) Size : 8
An array decays to a pointer when you pass it to another function, so sizeof(arr) will give you the actual amount of memory allocated, only in the scope of the function in which arr was declared.
There's a common mistake:
char* a // is a pointer
char b[] // is an array
when using:
char b[5]; // is an array of 5 bytes
sizeof(b); // 5
// but
char* a = b;
sizeof(a); // 8 (x64)
the last sizeof(a) is giving you the sizeof char * which is a pointer.
You can pass the name of an Array as a Pointer to the size() function, but in that function, the argument is treated as Pointer.

char * point to element not the address

void reverse(char * str){
char * end = str;
cout << "str" << str << endl;//ABCDE
cout << "end" << end << endl;//ABCDE
char tmp;
if(str){
while(*end){++end; cout << end << endl;}//ABCDE-->BCDE-->CDE-->DE-->E--> NULL
--end;//end=E
cout <<"--end" << end << endl;
while(str<end){// do swap
tmp = *str;//*str = str[0]
*str++ = *end;//*end = last ele in str[]
*end-- = tmp;
}
}
}
My input is
char test[] = "ABCDE";
cout << test << endl; //ABCDE
reverse(test);
cout << test << endl; //EDCBA
I am feeling not good about the pointer, since c++ primer book says char* pointer to the first element of an array, but when I output the pointer end, it is the content of an array not the address.
Also, reverse(test), I mean to give the address of the first element in an array to the pointer, but it turns out give the whole elements to the pointer.
A char* variable is a pointer to a char. A char[] is an array of char. Now, an array of char can be accessed through a pointer, and for char* it is commonly used for string processing (it's used although for other types, but for char it's much more common).
char test[6] = "ABCDE";
char *start = &test[0]; // will point on A
Accessing the array with the pointer can be done with pointer arithmetic:
char *end = start + 5; // equivalent to char *end = &test[5]
Now when you do:
cout << test;
or
cout << start;
It's actually calling an overload of operator<< that takes a const char*. What this operator does is that it print char starting from the pointer passed until it reaches a null char ('\0').
If you want to print the address contained in the pointer and not the string, you have to cast it to void*:
cout << static_cast<void*>(start);
std::cout is overloaded to print strings for char* .
Try:
char *test = "ABCDE";
std::cout << (void *) test << std::endl;