I'm trying to understand a part of my professor's code. He gave an example for a hw assignment but I'm not sure how to understand this part of the code..
Here is the code:
void addTask(TaskOrAssignment tasks[], int& taskCount, char *course, char *description, char *dueDate)
{
tasks[taskCount].course = course;
tasks[taskCount].description = description;
tasks[taskCount].dueDate = dueDate;
taskCount++;
}
Question: Is "tasks[taskCount].course = course;" accessing or declaring a location for char course?
I hope I could get this answered and I'm pretty new to this site too.
Thank you.
tasks[taskCount].course = course;
Let's break this down a piece at a time. First of all, we are using the assignment operator (=) to assign a value of one variable to another variable.
The right hand side is pretty simple, just the variable named course which is declared as a char*.
It is assigned to the variable tasks[taskCount].course. If you look at the parameters of the method, you can see that tasks is declared as an array of TaskOrAssignment objects. So tasks[taskCount] refers to one of the elements of this array. The .course at the end refers to a field named course in that object. Assuming that this code compiles, that field is declared as a char* in the TaskOrAssignment class.
Most likely, both course variables represent a string of characters. (This originates from C.) When all is said and done, both course and tasks[taskCount].course point to the same string buffer.
course is a char pointer, it points to the block of memory in stack or heap storing the '\0' terminated string.
tasks[taskCount].course is also a char pointer, the assignment just lets tasks[taskCount].course point to same memory address that course does.
course is a char* (a pointer to char). Presumably, the course member of TaskOrAssignment is also a char*. All that line does is assign the value of course to the member course of the taskCountth element in the array.
Presumably, the course argument is intended to be a pointer to the first character in a null-terminated C-style string. So after this assignment, the course member of the array element will point at that same C-style string. However, of course, the pointer could really be pointing anywhere.
Related
I'm given a method header as so:
char* thisMethod(char* input){}
is it possible to say,
char var = input[0];
? I know that "input" will be in the form of a char array.
I'm obviously new to C++ pointers are throwing me off. I tried researching how to work with char pointer function arguments but couldn't find anything specific enough to help. Thanks for the help.
There is a misconception that may lead you into further troubles:
I know that "input" will be in the form of a char array.
NOPE: By the scope of that function, input is a pointer to a character. The function has no way to know where such a pointer comes from.
If it has been taken from an array upon calling the function than it will be a pointer to the first element of that array.
Because pointer have an arithmetic that allows to add offsets and because the [] operator applied to pointers translates as a[b] = *(a+b) by definition, in whatever code, if a is a pointer, *a and a[0] are perfect synonymous.
Think to an array as a sequence of boxes and a pointer as your hand's index finger
adding an offset to a finger (like finger+2) means "re-point it aside" and de-referencing it (like *finger) means "look inside what it points to".
The [] operator on pointers is just a shortcut to do both operations at once.
Arrays are another distinct thing. Don't think to them when dealing with pointers, since -in more complex situations, like multidimensional array or multi-indirection pointers - the expression a[b][c] won't work anymore the same way.
There are two ways to get a value from a pointer, * and []. The following are equivalent:
char var1 = *input;
char var2 = input[0];
Using the brackets is more common when you know you were passed an array, since it allows you to supply an index. You need some way of knowing where the end of the array is so that you don't attempt any access past it, your function is missing that important detail.
As long as it's inside the function and input points to something valid ( not NULL/nullptr and not a garbage location ) then doing char var = input[0]; is just fine. It's the same as char var = *input.
P.S If it's supposed to be a string I recommend using std::string.
This is a simple operator overloading program I learned and I can't understand exactly why the parameterized constructor is using '*st' and not just 'st' or '&st'.
Now, I know the difference between passing by reference, address and value.
In the given example, I passed a string. If it was passing by reference, the argument in the parameterized constructor would have been '&st'. I'm not sure if it is passing the string by address.
Basically, I don't know how the code is working there. Please explain that and also why using '&st' in place of '*st' isn't working.
class tyst
{
int l;
char *p;
public:
tyst(){l=0;p=0;}
tyst(char *st)
{
l=strlen(st);
p = new char[l];
strcpy(p,st);
}
void lay();
tyst operator + (tyst b);
};
void tyst::lay()
{
cout<<p<<endl;
}
tyst tyst::operator+(tyst b)
{
tyst temp;
temp.l=l+b.l;
temp.p = new char[temp.l];
strcpy(temp.p,p);
strcat(temp.p,b.p);
return temp;
}
int main()
{
tyst s1("Markus Pear");
tyst s2("son Notch");
tyst s3;
s3=s1+s2;
s3.lay();
return 0;
}
So, I'd really appreciate if anyone can clear this up for me.
st is a C-style string. Passed by value
tyst(char st)
you would merely get a single character.
Passed by reference
tyst(char & st)
You would also get only a single character, but you could modify it. Not so useful in this case. You could also pass in a reference to a pointer, but I don't see much use to that, either.
How this is working
tyst(char * st)
says that the function will take a pointer, and that pointer may be pointing to a single character, the first of an unknown number of characters, absolutely nothing, or complete garbage. The last two possibilities are why use of references is preferred over pointers, but you can't use a reference for this. You could however use a std::string. In C++, this would often be the preferred approach.
Inside tyst, the assumption that an unknown, but null-terminated, number of characters is pointed at, and this is almost what is being provided. Technically, what you are doing here with
tyst s1("Markus Pear");
is illegal. "Markus Pear" is a string literal. It may be stored in non-writeable memory, so it is a const char *, not a char *.
The constructor is expecting a pointer to a c-string (null terminated character array). Applying pointer arithmetic to it will allow access to the entire string. Note that new[] returns a pointer to the first element; it is (one way) how pointers are used.
Aside from the syntax errors, it makes no sense to pass a single character by reference to the class. It isn't interested in a single character, it is interested in where the beginning of the array is.
It would be like asking somebody what their home address is, and they give you a rock from their lawn.
The nearest question on this website to the one I have had a few answers that didn't satisfy me.
Basically, I have 2 related questions :
Q. If I do something like :
char a[]= "abcde"; //created a string with 'a' as the array name/pointer to access it.
a[0]='z'; //works and changes the first character to z.
But
char *a="abcde";
a[0]='z'; //run-time error.
What is the difference? There is no "const" declaration, so I should be free to change contents, right?
Q. If I do something like :
int i[3];
i[0]=10; i[1]=20; i[2]=30;
cout<<*++i; //'i' is a pointer to i[0], so I'm incrementing it and want to print 20.
This gives me a compile-time error, and I don't understand why.
On the other hand, this works :
int *i=new int[3];
i[0]=10; i[1]=20; i[2]=30;
cout<<*++i; //Prints 20.
Thanks for the help.
Q
char *a="abcde";
a[0]='z'; //run-time error.
Ans - Here a is pointing to string literal stored in read only location. You cannot modify string literal
Q
int i[3];
i[0]=10; i[1]=20; i[2]=30;
cout<<*++i;
Ans- Array and Pointers are not same thing. Here i is not a pointer.
You need lvalue for increment operand
You can do :
int *p = &i[0];
std::cout<<*++p;
In last case operator new returns a pointer to a allocated memory space, so its possible.
Question 1
The trouble is that it is still const.
A string literal actually has the type char const*.
But when they designed C++03 they decided (unfortunately) that conversion from char const* to char* is not an error. Thus the code:
char *a="abcde";
Actually compiles without error (even though the string is const). BUT the string literal is still a const even though it is being pointed at via a non const pointer. Thus making it very dangerous.
The good news is that most compilers will generate a warning:
warning: deprecated conversion from string constant to ‘char*’
Question 2
cout<<*++i; //'i' is a pointer to i[0], so I'm incrementing it and want to print 20.
At this point i is not a pointer. It's type is still an array.
It is not a valid operation to increment array.
The thing you are thinking about; is that arrays decay into pointers at the drop of a hat (like when you pass them to functions). Unfortunately that is not happening in this situation and thus you are trying to increment an array (which does not make sense).
Bozo(const char * fname, const char * lname); // constructor prototype
In this case, you would use it to initialize new objects as follows:
Bozo bozetta = Bozo("Bozetta", "Biggens"); // primary form
Bozo fufu("Fufu", "O’Dweeb"); // short form
Bozo *pc = new Bozo("Popo", "Le Peu"); // dynamic object
I just have a few questions regarding this. First is that, why is const needed before char? or why is it there?. Also, why is it declaring as a pointer?
Second, is there any difference between the "primary form" and the "short form?"
Third question is that in Java, I used string variables for the formal parameters, but in C++ it's in char? I thought char can only contain a single alphabet, and it's not a char array. Could I do this with string instead?
First is that, why is const needed before char? or why is it there?. Also, why is it declaring as a pointer?
I'll start by answering your last question first. This is declared as a pointer so the constructor can accept an array of characters. The const is there to indicate that the characters being pointed to are not modified inside this bozo constructor. This is important because your example usage can pass in C-style string literals which typically reside in read-only memory portion of your program. Any attempts to modify such a string literal is undefined behavior.
Second, is there any difference between the "primary form" and the "short form?"
The first form is creating a temporary Bozo object on the right-hand side and that object is used to initialize bozetta on the left-hand side. Now you might think that an extra copy happens with this form but that isn't the case. The C++ standard is worded in such a way so that it permits the compiler to skip this unnecessary extra copy during construction by eliding. So in practice, you'll find that on all modern C++ compilers you try this on, bozetta will be constructed using the prototype you showed above -- no extra copying happens.
The second form explicitly constructs a Bozo object using a Bozo constructor that can accept two string literals as parameters.
These two forms have the same behavior assuming that constructor isn't declared explicit.
I thought char can only contain a single alphabet, and it's not a char array.
That is correct, a char can only hold one byte worth of information. C and C++ doesn't have an actual native string type, not like the type you're use to like in other languages. So a "string" is really just a bunch of chars laid out in a contingent block of memory. Your Bozo constructor above can work with this block by taking a pointer to where that block starts as input.
Could I do this with string instead?
Yes you can and that is actually the preferred way you should do this by using std::string. The constructor declaration would look like this:
Bozo(std::string fname, std::string lname);
// or to avoid potential copying of long strings
Bozo(const std::string &fname, const std::string &lname);
Yes Aaron
1 Ans: const is needed before char because here we are wanting not the value of the string to be change mistakenly.Const will keep remain the original value because we pass to constructor Pointer ( by ref ).
1 Ans: Bozo bozetta = bozo(“Bozetta”, “Biggens”); // primary form
Delcare Bozo bozetta = bozo ( "Bozetta", "Biggens" ) ; Ya there is a lot difference between short and primary is that we declaring an object of type Bozo and and assigning it new object values.
3 Ans: Yes you are correct that char contains only 1 character at a time but here you declared char * ( char pointer ) which is mean char array. Char pointer is consider String in C++.
Pointers have always made me blank about the logic I intend to use in code, If someone can help me understand a few concepts that would be really helpful. Here's a code snippet from my program,
vector <char> st;
char *formatForHtml(string str, string htmlTag)
{
string strBegin;
strBegin = "<";
strBegin.append(htmlTag);
strBegin.append(">");
strBegin.append(str);
string strEnd = "</";
strEnd.append(htmlTag);
strEnd.append(">");
strBegin.append(strEnd);
st.resize(strBegin.size());
for (int i =0;i <strBegin.size();i++) {
st[i] = strBegin.at(i);
}
return &st[0];
}
In the code above if I have to return address of st[0], I have to write the function of type char *. I need to know the reason to do so, also if address is the integer value why can I not define function as an int type?
P.S. It's a beginner level doubt.
You don't tell us what st is, so we can't tell whether the code is
totally incorrect, or just bad design. If st is a typo for str
(just guessing, since str isn't used anywhere), then you have
undefined behavior, and the program is incorrect, since you're returning
a pointer into an object which has been destructed. At any rate, a
function like formatForHtml should return an std::string, as a
value, and not a pointer (and certainly not a pointer to a non-const).
I might add that you don't use a loop to copy string values character by
character. std::string acts as a normal value type, so you can just
assign: st = strBegin;.
EDIT:
Just for the record, I've since reexamined your code. The natural way
of writing it would be:
std::string
formatForHtml( std::string const& cdata, std::string const& tag )
{
return '<' + tag + '>' + cdata + "</" + tag + '>';
}
No pointers (at least not visible---in fact, "+ operator), and full use of
std::strings facilities.
I have to write the function of type 'char *' I need to know the reason to do so
There's no reason to do so. Just return a std::string.
From the looks of your code, st is a std::vector<char>. Since std::vector has continuous memory, &st[0] is the address of the first char in the vector, and thus points to the not null-terminated string that the vector represents, which isn't very helpful outside the function because you can't find the length.
That's awkward code, you're expecting 'str' as an argument, but then you return its memory location? Why not return the string itself?
Your code there has a few typos. (Did you mean 'str' when you typed 'st'? If not, then where is 'st' defined?)
As for why you can't define the function as "int" type, that is because an "int" is a different type to "pointer to char".
Personally, I would return 'string', and just have a 'return str' at the end there.
Pointer is pointer, not integer value. Code is right if and only if st is global variable or declared as static in this function. But return string is preferably, than return pointer.
Why don't you use string as return type for your function?
First: a pointer is an adress of something lying in memory, so you can't replace it with an integer (only with some dirty tricks).
Second: &st[0] is the adress of the internal buffer the string uses to store its content. When st goes out of scope (or is reused for the next call), it will be overwritten or given back to the heap manager, so the one calling this function will end with some garbage.
Btw, most of your function does unnessesary work which the string class can do by itself (for example copiing strBegin to st).
Simple.
string str
is something that contains a bunch characters.
str[0]
return the first character.
Therefore,
&str[0]
gives you the address of the first character, therefore it's a "char *" --- "char" being whatever the pointer points to, "*" being the "address of" part of the pointer. The type of the pointer is about the object being pointed to.
Also, addresses may be just "integers" on the hardware level (everything is an integer... except for integers themselves, they are a bunch of bools), but that doesn't mean anything for a higher level language. For a higher level language, a pointer is a pointer, not an integer.
Treating one as another is almost always an error, and C++11 even added the nullptr keyword so we don't have to rely on the one valid "pointer is an integer" case.
And btw, your code won't work. "str" only exists for the duration of the function, so when the function returns "str" ceases to exist, which means the pointer you have returned points into a big black nowhere.