I'm trying to create an array of pointers using my professors example in class. I can't seem to get it to work though.
char * ISBN[] = {
"1-214-02031-3",
"0-070-21604-5",
"2-14-241242-4",
"2-120-12311-x",
"0-534-95207-x",
"2-034-00312-2",
"1-013-10201-2",
"2-142-1223",
"3-001-0000a-4",
};
This is my professors example of declaring an array of pointers of type char. He says this is what we should do for the assignment. Sadly, I'm getting the error -
Error (active) E0144 a value of type "const char *" cannot be used to initialize an entity of type "char *" -
I've asked about this before and someone said that char * has been deprecated. But the professor says that this is the declaration that we should use for the assignment. How would I go about trying to figure out how to get this array working? What exactly is this declaration doing?
const char * ISBN[] = {
"1-214-02031-3",
"0-070-21604-5",
"2-14-241242-4",
"2-120-12311-x",
"0-534-95207-x",
"2-034-00312-2",
"1-013-10201-2",
"2-142-1223",
"3-001-0000a-4",
};
I guess I just needed to add const in front of char *. I still got much to learn. Thanks everyone.
It is simply because you are trying to assign string literals to char pointer.In c++ string literals are const char pointer because as string literals are stored in read-only memory.Another reason is for optimisation for compilers(storing only one instance of a literal that is repeated many times in the source). So you get multiple pointers to the same memory, instead of each occupying a separate chunk of memory.
Related
I have read a lot about the subject and I am confused .
What used to work in a C file ,not working on a cpp file :
char *builtinFunctions[20];
Then I get error on the strcpy function here :
void Intepreter::setBuiltIns(char *builtins)
{
strcpy(builtinFunctions, builtins); // no matching function call to strcpy
}
I probably don't understand the basics here, but why in C++ this will not work ( do i need to use = instead ? )
strcpy(char *, const char*) = thats the structure
if I change the builtinFunctions from being a pointer it works.
EDIT:
The reason for being a const before this edit is that I read here :
Why is conversion from string constant to 'char*' valid in C but invalid in C++
that char *builtinFunctions[20]; will produce warning when :
builtinFunctions[0]="me";
and it did. I could fix it by removing the const .
This is an array of pointers to char.
char *builtinFunctions[20];
So you call
strcpy(builtinFunctions, builtins);
gets treated as strcpy(char **, char*), not as strcpy(char *dest, const char *src). So you get a mismatch for first parameter type.
EDIT:
So let's suppose builtinFunctions is "an array of words" you wish to populate, with void Intepreter::setBuiltIns(char *builtins) meant to do just that with it's first parameter being a pointer to a new incoming word. (And you're doing this in a C-style manner. Well, up to you.)
Some things to consider.
If you declare an array type arrName[N]; then the array's name
being used all alone without index is treated as a variable of type
type *arrName. If you type is initially char *, then
builtinFunctions by itself is of type char**. That's why your
strcpy fails, but strcpy(builtinFunctions[someIndex], builtins);
works.
Before invoking strcpy you should consider, if you have a
destination space allocated. builtinFunctions[someIndex] is of
type char *. Where does it point to? Is it a valid pointer to an
allocated space, or a gateway to hell of undefined behaviour strcpy will happily take you to?
In the following code snippet, I am not able to understand why the error is coming on LineA , but no error in Line B ?
//Global
char strA[80] = "A string to be used for demonstration purposes";
int t=60;
int main(void)
{
strA[80] = "I am trying to modify the source"; //Line A, gives error
t=60; //Line B, no errors
}
The error is:
2 IntelliSense: a value of type "const char *" cannot be assigned to
an entity of type
"char" c:\users\hu\cplustutorial.cpp 69 12 CPLUStutorial
I am not having the char string as const, so why this error?
Compiling with MS VS 2010.
This char strA[80] = "A string to be used for demonstration purposes"; initializes your array.
This strA[80] means a single character within that array. How can you store multiple characters in a single char. Use strcpy to copy the new string.
You are trying to assign the 80th element of strA (which incidentally doesn't exist) with a const char*, not the char[] itself. Also, you tagged the question as C++, so why use char[] instead of std::string?
In C++, the type of a string literal is const char[], not plain char[], so what you are trying to do is illegal by the C++ standard, hence the error you are seeing.
In order to modify the string you will first need to copy it, either using the C library function strcpy or (better) with a std::string.
You have to understand a string of character(string literal) has a type of const char * and you are trying to store it inside a single char(char[80]). Thats why its giving you error.Check this out http://www.stackoverflow.com/questions/20294015/.
This question already has answers here:
C++ Error: Incompatible types in assignment of ‘char*’ to ‘char [2]
(3 answers)
Closed 9 years ago.
So I trying to build this program that will take two char and a double. Once the user has input the information. I will transfer the information to an object by using the function below.
But every time I try to compile i get this error incompatible types in assignment of const char* to char [20]. Can anyone give me a hand and clarify when im not understanding. Thanks in advance.
void Molecule::set(const char* sym, const char* type, double weighT);
And this how I call it.
molecule[i].set(symbol, description,weight);
And within the set() function I just have to transfer the values inpputed to my private member in my object which i did by using this-> function.
////So This part is supposed to transfer the value to my Class Molecule private members////
this->symbol_ = sym;
this->type_ = type;
this->weight_ = weighT;
///////Here is my Class Molecule////////
class Molecule{
private:
char symbol_[20];
char type_[20];
double weight_;
public:
void set(const char* sym, const char* type, double weighT);
void display() const;
};
You need to use strcpy or similar to copy the strings from your char * to your class's char []. Using = is attempting to copy the pointer but they are indeed incompatible types.
This code
this->symbol_ = sym;
this->type_ = type;
is invalid. Arrays have no the copy assignment operator. You should use either standard C function strcpy or strncpy that are declared in header <cstring>
For example
std::strncpy( this->symbol, sym, 20 );
this->symbol[19] = '\0';
std::strncpy( this->type, type, 20 );
this->type[19] = '\0';
Also it is a good idea to assign a name for magic number 20 either using an enumerator or static constant.
Also instead of character arrays you could use standard class std::string that has several overloaded assignment operators.
symbol_ is a char[], you need to use stcpy to fill it.
In set method :
this->symbol_ = sym;
should becomes
stncpy(this->symbol_, sym, 20);
Or simpler define symbol_ as an std::string replacing :
char symbol_[20];
with
std::string symbol_;
Pointers and Arrays are not the same thing, although it is easy to believe that they are.
Arrays can be passed as arguments to functions that request pointers because of pointer decay, and that can lead people to believe that they are interchangeable.
See this article: What is array decaying?
When you declare symbol_[20], this tells the class to allocate 20 bytes when the object is created. symbol_ will always point to this allocation. You cannot reassign it as you could with a pointer.
You probably will want to copy the text pointed to by sym using std::strncpy. Be careful, though. If the string pointed to by sym is bigger than 19 characters (19 + 1 for the null character at the end), then you will need to terminate your symbol_ array with a null character (\0) manually for it to be a valid string.
#include <cstring>
...
std::strncpy(symbol_, sym, sizeof(symbol));
symbol_[19] = '\0';
I didn't get the chance to compile the code above, so, it might be best to study the example at the end of this article:
http://www.cplusplus.com/reference/cstring/strncpy/?kw=strncpy
I'm new to C++ and I'm playing with pointers. I can't figure out why this piece of code doesn't work for me. Can you tell me what's wrong with it?
char * name = "dharman";
char *ptr = name+3;
*ptr = 'a';
printf("%s", name);
I get unhandled exception all the time.
This alone is an error:
char * name = "dharman";
The string is in constant memory but the pointer's type indicates it can be modified. Attempting to modify it produces undefined behavior: on other platforms the program will work but you got unlucky.
This was a quirk in C++03; the newer C++11 spec makes it illegal. The reason it was ever done was C compatibility.
Whether you're writing in C++ or plain C, the solution is simple:
char name[] = "dharman";
Now the compiler stores the data in read-write memory because you have asked for an array of char, not a pointer to some other memory.
String literals, like "dharman", are read-only and you cannot modify them. Instead, create and initialize an array that is not read only.
char name[] = "dharman";
name is a pointer to a string literal "dharman", which is located in read-only memory.
In your statement *ptr = 'a', you are trying to modify this string literal, which results in Undefined Behavior
It doesn't work because "dharman" is constant, it's a string literal. You cannont change it!
String literals are usually placed in read-only segments of memory.
You are trying to modify a constant string.
You need to copy the constant first to some memory that you own.
Try this:
char *name = (char*) malloc(10);
memcpy(name, "dharman", strlen("dharman"));
...
You are setting name to point at a const string and then trying to modify it. Copy the string to a modifiable location:
char *name = (char*) malloc(strlen("dharman") + 1);
memcpy("dharman", name, strlen("dharman") + 1);
The reason for unhandled exception in your case is.In your code
char *ptr= name+3;
consider the base address of name as eg:23300, so char *ptr =name+3 will be equal to
23300+(3*sizeof(char)).so now ptr points to 23300+(3*1)=23303.each element occupies one bye for char so ptr will point to letter 'a' in "dharman".since "dharman" is char const you can't its value that's why you are getting error.if u remove the line *ptr=3.the code will work without out any issue.I hope you find this post useful.
Been thinking, what's the difference between declaring a variable with [] or * ? The way I see it:
char *str = new char[100];
char str2[] = "Hi world!";
.. should be the main difference, though Im unsure if you can do something like
char *str = "Hi all";
.. since the pointer should the reference to a static member, which I don't know if it can?
Anyways, what's really bugging me is knowing the difference between:
void upperCaseString(char *_str) {};
void upperCaseString(char _str[]) {};
So, would be much appreciated if anyone could tell me the difference? I have a hunch that both might be compiled down the same, except in some special cases?
Ty
Let's look into it (for the following, note char const and const char are the same in C++):
String literals and char *
"hello" is an array of 6 const characters: char const[6]. As every array, it can convert implicitly to a pointer to its first element: char const * s = "hello"; For compatibility with C code, C++ allows one other conversion, which would be otherwise ill-formed: char * s = "hello"; it removes the const!. This is an exception, to allow that C-ish code to compile, but it is deprecated to make a char * point to a string literal. So what do we have for char * s = "foo"; ?
"foo" -> array-to-pointer -> char const* -> qualification-conversion -> char *. A string literal is read-only, and won't be allocated on the stack. You can freely make a pointer point to them, and return that one from a function, without crashing :).
Initialization of an array using a String literal
Now, what is char s[] = "hello"; ? It's a whole other thing. That will create an array of characters, and fill it with the String "hello". The literal isn't pointed to. Instead it is copied to the character-array. And the array is created on the stack. You cannot validly return a pointer to it from a function.
Array Parameter types.
How can you make your function accept an array as parameter? You just declare your parameter to be an array:
void accept_array(char foo[]);
but you omit the size. Actually, any size would do it, as it is just ignored: The Standard says that parameters declared in that way will be transformed to be the same as
void accept_array(char * foo);
Excursion: Multi Dimensional Arrays
Substitute char by any type, including arrays itself:
void accept_array(char foo[][10]);
accepts a two-dimensional array, whose last dimension has size 10. The first element of a multi-dimensional array is its first sub-array of the next dimension! Now, let's transform it. It will be a pointer to its first element again. So, actually it will accept a pointer to an array of 10 chars: (remove the [] in head, and then just make a pointer to the type you see in your head then):
void accept_array(char (*foo)[10]);
As arrays implicitly convert to a pointer to their first element, you can just pass an two-dimensional array in it (whose last dimension size is 10), and it will work. Indeed, that's the case for any n-dimensional array, including the special-case of n = 1;
Conclusion
void upperCaseString(char *_str) {};
and
void upperCaseString(char _str[]) {};
are the same, as the first is just a pointer to char. But note if you want to pass a String-literal to that (say it doesn't change its argument), then you should change the parameter to char const* _str so you don't do deprecated things.
The three different declarations let the pointer point to different memory segments:
char* str = new char[100];
lets str point to the heap.
char str2[] = "Hi world!";
puts the string on the stack.
char* str3 = "Hi world!";
points to the data segment.
The two declarations
void upperCaseString(char *_str) {};
void upperCaseString(char _str[]) {};
are equal, the compiler complains about the function already having a body when you try to declare them in the same scope.
Okay, I had left two negative comments. That's not really useful; I've removed them.
The following code initializes a char pointer, pointing to the start of a dynamically allocated memory portion (in the heap.)
char *str = new char[100];
This block can be freed using delete [].
The following code creates a char array in the stack, initialized to the value specified by a string literal.
char [] str2 = "Hi world!";
This array can be modified without problems, which is nice. So
str2[0] = 'N';
cout << str2;
should print Ni world! to the standard output, making certain knights feel very uncomfortable.
The following code creates a char pointer in the stack, pointing to a string literal... The pointer can be reassigned without problems, but the pointed block cannot be modified (this is undefined behavior; it segfaults under Linux, for example.)
char *str = "Hi all";
str[0] = 'N'; // ERROR!
The following two declarations
void upperCaseString(char *_str) {};
void upperCaseString(char [] _str) {};
look the same to me, and in your case (you want to uppercase a string in place) it really doesn't matters.
However, all this begs the question: why are you using char * to express strings in C++?
As a supplement to the answers already given, you should read through the C FAQ regarding arrays vs. pointers. Yes it's a C FAQ and not a C++ FAQ, but there's little substantial difference between the two languages in this area.
Also, as a side note, avoid naming your variables with a leading underscore. That's reserved for symbols defined by the compiler and standard library.
Please also take a look at the http://c-faq.com/aryptr/aryptr2.html The C-FAQ might prove to be an interesting read in itself.
The first option dynamically allocates 100 bytes.
The second option statically allocates 10 bytes (9 for the string + nul character).
Your third example shouldn't work - you're trying to statically-fill a dynamic item.
As to the upperCaseString() question, once the C-string has been allocated and defined, you can iterate through it either by array indexing or by pointer notation, because an array is really just a convenient way to wrap pointer arithmetic in C.
(That's the simple answer - I expect someone else will have the authoritative, complicated answer out of the spec :))