pointers in c++ debugging - c++

I am currently trying to learn C++ from a book that I got from a friend of mine a couple of days ago. I I've seen some codes as a quiz in the book that I need to solve. So I tried to solve them but I'm not sure if my assumption is right.
This is the first one
char* r(char *g){ // can someone explain this line for me? I'm not sure what is it saying
char ch = 'B'; // is the code going to be correct if I changed char ch to char* ch?
return &ch; // since this is &ch, then the previous line should be char* ch, am I right?
}
The second code:
char* a;
a = new char[strlen(b)]; // will this line cause a compiling error just because b is undefined ? since there is no length for b because it's not even there?
strcpy(a,b); // since we're using strcpy() a and b has to be pointers am I right?
I am not asking for the answers, I need someone to tell me whether am right or wrong and why please.

char* r(char *g){ // can someone explain this line for me? I'm not sure what is it saying
Declares a function, r which takes one argument, a pointer g to contain the address of one or more characters.
char ch = 'B';
Declares a variable, ch of type char and assigns it a value 'B'. That is - it will contain a number which is the position in the ASCII chart of the letter B. It's going to contain the number 66, but when you print it out, it will produce the letter 'B'. (see http://www.asciitable.com/)
This variable will likely be on the stack. It could be in a register, but compilers are generally smart and the next line will ensure it is on the stack.
return &ch;
In this context, & is the address of operator.
return address_of(ch);
Since ch is of type char, &ch produces a value which is of type char*.
char* a;
Declares a variable a with no initial value. This is a bad thing to get into the habbit of writing.
a = new char[strlen(b)];
You say that b doesn't exist, but I think it's assumed to be of type char* - a pointer to one or more characters. In C and C++ a "C-String" is an array of 'char' values (characters) terminated by a char of value 0 (not the character '0', which has an ASCII value of 48, but 0, or '\0'). This is called a 'terminating nul' or a 'nul character' or a 'nul byte'.
The string "hello" is actually representable as an array { 'h', 'e', 'l', 'l', 'o', 0 }. Contrast with "hell0", which would be { 'h', 'e', 'l', 'l', '0', 0 };
The function strlen counts the number of characters from the address it is called with until it finds a nul. If b was the address of "hello", strlen would return 5.
new allocates memory for an object, or in this case an array of objects of type char, the number of which is the return value of strlen.
size_t len = strlen(b);
char* a = new char[len];
At this point in the code, recall my explanation about terminating nul and that strlen returns the number of characters before it finds the 0. To store a C-string you need the number of characters PLUS space for a terminating NULL.
If b is the string "A", it consists one character ('A') but two *char*s - 'A', and 0. Strlen returns the number of characters.
strcpy(a, b);
This will copy the characters pointed to by b to the address at a, *including the terminating nul.
The bug here is that you only allocated enough memory for the characters.
char* a = new char[strlen(b) + 1];
strcpy(a, b);
Again - strlen is always going to return the length - the number of characters, and you're always going to want one more than that, for the nul.
would be correct - otherwise you're going to overwrite the memory allocated to you and cause a corruption.
--- EDIT ---
Throwing some of this together, live demo here: http://ideone.com/X8HPxP
#include
#include
int main() {
char a[] = "hello";
std::cout << "a starts out as [" << a << "]\n";
// C/C++ arrays are 0-based, that is:
a[0] = 'H'; // changes a to "Hello"
std::cout << "a is now [" << a << "]\n";
std::cout << "strlen(a) returns " << strlen(a) << "\n";
// But that is based on counting characters until the 0.
a[3] = 0; // one way to write it,
a[3] = '\0'; // some people prefer writing it this way.
std::cout << "a changed to [" << a << "]\n";
std::cout << "strlen(a) is now " << strlen(a) << "\n";
return 0;
}

First Code:
r is function name having return type char* i.e. reference type and accepting parameter of reference type char* g.
'B' is assigned to ch variable.
r function returns the address of ch variable.
According to me no correction required in First code.
Second Code:
Yes it will cause compilation error at line 2 as b is not declared or defined.

1st Code:
You are defining a function called r which accepts a pointer to a char and returns a pointer to a char.
char* r(char *g){
//stack char variable ch is initialized to B
//changing char ch to char *ch will compile (with a warning) but then the address pointed by ch will contain garbage (value of 'B' projected as an address).
char ch = 'B';
//you are returning the address of ch which as seen above is a stack variable so you are causing undefined behavior. You should avoid this.
return &ch;
}
2nd Code:
char* a;
// if b is undefined as you state then following line will cause compiling error. strlen() will calculate the length of the area at runtime so b must be at lease defined first.
a = new char[strlen(b)];
//a is a pointer as you defined it above and points to the heap memory allocated by new
strcpy(a,b);

char* r(char *g){
here r() is function which take char* as argument and return char*
char ch = 'B';
return &ch;
Here, ch is char locally defined and you are returning it. This is not good. Better use char*. Also char will have only one character whereas if you use char* you can have more than one.
char* ch = "Thats My string";
return ch; //Notice ch is a pointer. No need to use &
Second Code:
char* a;
a = new char[strlen(b)];
If b is undefined, sure there will be error. If b is char* with some value assigned to it strlen will provide you length of string which b is having. so this looks good.
strcpy(a,b); // since we're using strcpy() a and b has to be pointers am I right?
Yes you are right! You can use strncpy instead.

Related

pointer arithmetic on arrays

When I run the code below my output is not what I expect.
My way of understanding it is that ptr points to the address of the first element of the Str array. I think ptr + 5 should lead to the + 5th element which is f. So the output should only display f and not both fg.
Why is it showing fg? Does it have to do with how cout displays an array?
#include <iostream>
using namespace std;
int main()
{
char *ptr;
char Str[] = "abcdefg";
ptr = Str;
ptr += 5;
cout << ptr;
return 0;
}
Expected output: f
Actual output: fg
When you declare:
char Str[] = "abcdefg"
The string abcdefg is stored implicitly with an extra character \0 which marks the end of the string.
So, when you cout a char* the output will be all the characters stored where the char * points and all the characters stored in consecutive memory locations after the char* until a \0 character is encountered at one of the memory locations! Since, \0 character is after g in your example hence 2 characters are printed.
In case you only want to print the current character, you shall do this ::
cout << *ptr;
Why is it showing fg?
The reason why std::cout << char* prints the string till the end instead of a single char of the string is , because std::cout treats a char * as a pointer to the first character of a C-style string and prints it as such.1
Your array:
char Str[] = "abcdefg";
gets implicitly assigned an '\0'at the end and it is treated as a C-style string.
Does it have to do with how std::cout displays an array?
This has to do with how std::cout handles C-style strings, to test this change the array type to int and see the difference, i.e. it will print a single element.
1. This is because in C there are no string types and strings are manipulated through pointers of type char, indicating the beginning and termination character: '\0', indicating the end.

Trying to reverse a string and getting a bus error

I am trying to reverse a string (but that's not the problem that I have). The problem is trying to change the value of the string array given a certain index. However, every time I try to change the value at the index, I get a bus error. Namely, Bus error: 10. I'm not sure what this means. Also, I tried str[0] = "a" but this also gives me a bus error. Any suggestions to fix this?
#include <iostream>
using namespace std;
void reverse(char* str){
str[0] = 'a';
}
int main(){
char* str = "hello";
reverse(str);
}
Allocate your string as an array on the stack and not as a pointer into a possibly read-only segment of your program.
char str[] = "hello";
First of all, this line should atleast give you a warning:
char* str = "hello";
you are converting a string constant to a pointer, which is not allowed.
To fix your code, you should use, char str[] = "hello" in main().
When you pass this array in reverse(), it decays to char*, now the question which you asked in previous answer's comment.
But when I write cout << str << endl;, why does it print out "hello"? Shouldn't it print only the first character of the string since it points to the first element of the array?
It is because the << operator on std::cout is overloaded. If you give it a char* or const char*, it treats the operand as a pointer to (the first character of) a C-style string, and prints the contents of that string:
const char * str= "hello";
cout << str; // prints "hello"
If you give it a char value, it prints that value as a character:
cout << *str; // prints "h"
cout << str[0]; // prints "h"

pointers *char and &char

I have doubt on below programme
#include "stdafx.h"
#include "stdio.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char *chr = "hello";
cout<<chr; //hello
cout<<endl;
cout<<*chr; //h
cout<<endl;
cout<<*(&chr); //hello
system("pause");
return 0;
}
why second cout prints h where as third one prints hello when represents the same
To be a little bit more explicit. chr is a pointer pointing to a chunk of memory where the characters 'h','e','l','l' and 'o' are stored. After the last character of chr is a terminating \0. This is needed to signal that the chunk pointed by chr is now over.
When passing chr to cout, cout will read (not cout it self but the underlying function wich is called by using the << operator) this chunk up to the terminating \0. When passing *chr to cout you dereference the pointer and simply pass the first character pointed by chr to cout ('h').
*(&chr) is the same thing as just chr because the adress-of operator gives you the adress of chr wich is a pointer to a pointer to character. Dereferencing it using * will then give you the pointer pointing to the chunk of memory starting with 'h' and coutwill again read up to the terminating \0.
EDIT
As birdypme pointed out correctly, the * operator (dereferencing operator) is the inverse to the address-of operator. It is like + and -. Therefore something like this
cout << *(&(*(&chr))) << endl;
will still be the same as
cout << chr << endl;
You can do this to infinity if you like to.
cout << *(&(*(&(*(&(*(&(*(&(*(&(*(&chr))))))))))))) << endl; // I hope i didn't miss a ')'
Because in the second case, you are passing to cout a single char, the one pointed by chr, that is the first of the C-string "hello".
In the second example you are dereferencing the pointer. This is the same as using chr[0] and in this case it is h.
In the last example you are taking the address of chr and then dereferencing:
&chr --> char**
*(&chr) --> char*
So at the and you again have a char*
Your statement
cout<<*chr; is same as cout<<chr[0];
because the pointer is dereferenced and passes only the first character pointed by chr
In case of cout<<*(&chr); , if i convert it into words, it would be, print the value present at the address of chr. Now since chris a pointer, you will get a pointer to a pointer by this statement &chrand the again you are dereferencing it, which gives you hello.

Does the null character get automatically inserted?

Is the C++ compiler supposed to automatically insert the null character after the end of the char array? The following prints "Word". So does the C++ compiler automatically insert a null character at the last position in the array?
int main()
{
char x[] = {'W', 'o', 'r', 'd'};
cout << x << endl;
return 0;
}
No, it doesn't. Your array x has only 4 elements. You are passing std::cout a pointer to char, which is not the beginning of a null-terminated string. This is undefined behaviour.
As an example, on my platform, similar code printed Word?, with a spurious question mark.
In C/C++ string literals are automatically appended with terminating zero. So if you will write for example
char x[] = "Word";
then the size of the array will be equal to 5 and the last element of the array will contain '\0'.
When the following record is used as you showed
char x[] = {'W', 'o', 'r', 'd'};
then the compiler allocates exactly the same number of elements as the number of the initializers. That is in this case the array will have only 4 elements.
However if you would write the following way
char x[5] = {'W', 'o', 'r', 'd'};
then the fifth element will contain the terminating zero because it has no corresponding initializer and will be zero-initialized.
Also take into account that the following record is valid in C but invalid in C++
char x[4] = "Word";
That is undefined behavior, and it printed "Word" as it might also have crashed.
No it doesn't. You yourself have to do that if you want to use it as a string or you want to use library functions for strings for that.
No, in this case you are just creating a non-null terminated array. In-case of a read based on null termination. Your program won't stop as it wouldn't find the null at last.
char x[] = "Word";
In this case 5 bytes would be allocated for x. Null at the end.
No, it doesn't. If you want it inserted automatically, use a string constant:
const char *x = "Word";
//OR
std::string const s = "Word";
const char *x = s.c_str();
//OR
char x[] = { "Word" }; //using the C++11 brace initializer syntax.
The simplest way to verify this is to look at the memory address for x using a debugger and monitor it and the next few bytes following it. Stop the debugger after the initialization and examine the memory contents.
No, if you want to use the char array as a string use this form of the initializer
char x[] = { "Word" };
Although it is not guaranteed, it seems my implementation always adds a \0 even if I am not requested.
I tested noNull[2] is always \0
char noNull[] = {'H', 'i'};
for (int i = 2; i < 5; ++i) {
if (noNull[i] == '\0') {
std::cout << "index " << i << " is null" << std::endl;
} else {
std::cout << "index " << i << " is not null" << std::endl;
}
}
output
index 2 is null
index 3 is not null
index 4 is not null

Difference between char* and char[]

I know this is a very basic question. I am confused as to why and how are the following different.
char str[] = "Test";
char *str = "Test";
char str[] = "Test";
Is an array of chars, initialized with the contents from "Test", while
char *str = "Test";
is a pointer to the literal (const) string "Test".
The main difference between them is that the first is an array and the other one is a pointer. The array owns its contents, which happen to be a copy of "Test", while the pointer simply refers to the contents of the string (which in this case is immutable).
The diference is the STACK memory used.
For example when programming for microcontrollers where very little memory for the stack is allocated, makes a big difference.
char a[] = "string"; // the compiler puts {'s','t','r','i','n','g', 0} onto STACK
char *a = "string"; // the compiler puts just the pointer onto STACK
// and {'s','t','r','i','n','g',0} in static memory area.
A pointer can be re-pointed to something else:
char foo[] = "foo";
char bar[] = "bar";
char *str = foo; // str points to 'f'
str = bar; // Now str points to 'b'
++str; // Now str points to 'a'
The last example of incrementing the pointer shows that you can easily iterate over the contents of a string, one element at a time.
One is pointer and one is array. They are different type of data.
int main ()
{
char str1[] = "Test";
char *str2 = "Test";
cout << "sizeof array " << sizeof(str1) << endl;
cout << "sizeof pointer " << sizeof(str2) << endl;
}
output
sizeof array 5
sizeof pointer 4
The first
char str[] = "Test";
is an array of five characters, initialized with the value "Test" plus the null terminator '\0'.
The second
char *str = "Test";
is a pointer to the memory location of the literal string "Test".
Starting from C++11, the second expression is now invalid and must be written:
const char *str = "Test";
The relevant section of the standard is Appendix C section 1.1:
Change: String literals made const
The type of a string literal is changed from “array of char” to “array
of const char.” The type of a char16_t string literal is changed from
“array of some-integer-type” to “array of const char16_t.” The type of
a char32_t string literal is changed from “array of some-integer-type”
to “array of const char32_t.” The type of a wide string literal is
changed from “array of wchar_t” to “array of const wchar_t.”
Rationale: This avoids calling an inappropriate overloaded function,
which might expect to be able to modify its argument.
Effect on original feature: Change to semantics of well-defined feature.
"Test" is an array of five characters (4 letters, plus the null terminator.
char str1[] = "Test"; creates that array of 5 characters, and names it str1. You can modify the contents of that array as much as you like, e.g. str1[0] = 'B';
char *str2 = "Test"; creates that array of 5 characters, doesn't name it, and also creates a pointer named str2. It sets str2 to point at that array of 5 characters. You can follow the pointer to modify the array as much as you like, e.g. str2[0] = 'B'; or *str2 = 'B';. You can even reassign that pointer to point someplace else, e.g. str2 = "other";.
An array is the text in quotes. The pointer merely points at it. You can do a lot of similar things with each, but they are different:
char str_arr[] = "Test";
char *strp = "Test";
// modify
str_arr[0] = 'B'; // ok, str_arr is now "Best"
strp[0] = 'W'; // ok, strp now points at "West"
*strp = 'L'; // ok, strp now points at "Lest"
// point to another string
char another[] = "another string";
str_arr = another; // compilation error. you cannot reassign an array
strp = another; // ok, strp now points at "another string"
// size
std::cout << sizeof(str_arr) << '\n'; // prints 5, because str_arr is five bytes
std::cout << sizeof(strp) << '\n'; // prints 4, because strp is a pointer
for that last part, note that sizeof(strp) is going to vary based on architecture. On a 32-bit machine, it will be 4 bytes, on a 64-bit machine it will be 8 bytes.
Let's take a look at the following ways to declare a string:
char name0 = 'abcd'; // cannot be anything longer than 4 letters (larger causes error)
cout << sizeof(name0) << endl; // using 1 byte to store
char name1[]="abcdefghijklmnopqrstuvwxyz"; // can represent very long strings
cout << sizeof(name1) << endl; // use large stack memory
char* name2 = "abcdefghijklmnopqrstuvwxyz"; // can represent very long strings
cout << sizeof(name2) << endl; // but use only 8 bytes
We could see that declaring string using char* variable_name seems the best way! It does the job with minimum stack memory required.