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?
Related
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.
In c++ we can write
1 char *s="hello"
but the below lines of program produces an error ( cannot convert char* to char)
2 char *s;
*s="hello";
I am confused here, what is difference between 1 and 2
why this error is coming?
In C++, a string literal is a constant array of characters, not just an array of characters like in C. Anyways, to assign to such a variable (Which is best avoided), you do not have to dereference the pointer. Dereferencing it accesses the first element, which is just a char. A char cannot hold an array of characters inside it, causing an error. This is more the reason why you should be using std::string.
Some compilers such as GCC provide extensions to make such code possible since it is not standards compliant code, and it would look like:
char* s = "hello";
s = "new string";
This generates the following warning in GCC (But still gets the expected result):
warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
Clang also has the same behavior with the same output (Also generating a warning)
A string is an array of characters. The start of a string therefore is const char *.
Therefore to reference a string, you can use const char * s = "hello";
However if you dereference a const char*, you get a const char. This isn't a string i.e. *s gives you 'h'.
In your code *s="hello";, you are saying "assign at the dereferened s the value "hello"". Dereferencing s is a character only, to which you are trying to assign a string.
The problem is the second asterisk in your second example.
The first code is this
char *s="hello";
The equivalent code is this
char *s;
s="hello";
No * before s in the second line.
Now as everyone is pointing out neither of these are legal C++. The correct code is
const char *s="hello";
or
const char *s;
s="hello";
Because string literals are constant, and so you need a pointer to const char.
I am confused here, what is difference between 1 and 2 why this error is coming?
As many others * in C++ means different things in different context:
char *s; // * here means that s type is a pointer to char, not just char
*s; // in this context * means dereference s, result of exression is char
int a = 5 * 2; // in this context * means multiply
so case 1 and 2 may look similar to you but they mean very different things hence the error.
#include <iostream>
using namespace std;
int main() {
int * a[5];
char * b[5];
cout<<a[1]; // this works and prints address being held by second element in the array
cout<<b[1]; // this gives run time error . why ?
return 0;
}
Can anyone please explain to me cout<<b[1] gives run-time error ?
Shouldn't both int and char array behave similar to each other ?
Because IOStreams are designed to treat char* specially.
char* usually points to a C-string, so IOStreams will just assume that they do and dereference them.
Yours don't.
As others have said, iostream formatted output operators consider char* to point to C-style string and attempt to access this string.
What others have not said so far, is that if you are interested in the pointer, you need to cast the pointer in question to void*. For example:
std::cout << static_cast<const void*>(buf[1]);
An output stream such as cout gives special consideration to char * that it does not give to other pointers. For pointers other than char *, it will simply print out the value of the pointer as a hexadecimal address. But for char *, it will try to print out the C-style (i.e. null terminated array of char) string referred to by the char *. Therefore it will try to dereference the char pointer, as #AlexD points in the comment to your post.
C++ (inheriting it from C) treats character pointers specially. When you try to print a[1] of type int* the address is printed. But when you try to print b[1] of type char* the iostream library - following the rest of the language - assumes that the pointer points to the first character of zero-terminated string of characters. Both your output statements are initialised behaviour, but in the case of char* crash is much more likely because the pointer is dereferenced.
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/.
I have a const char
const char example[] = "\x4D\x5A\xE8\x00\x00\x00\x00\x5B\x52\x45\x55\x89\xE5\x81\xC3";
and
DWORD* example2 = "\xAA\xBB\xCC\xDD";
and i want to change the last 4 bytes of example1 with those on example2
what can I do in C++?
i have tried memcpy , strcpy and strcpy_s with no luck
You should not modify a constant array!
Modifying a inherently constant object/variable leads to Undefined Behavior.
Just don't do it. Make a copy of it and modify that copy or if you want to modify the same array simply don't declare it as const.
Donot modify a constant string.
const char example[] = "\x4D\x5A\xE8\x00\x00\x00\x00\x5B\x52\x45\x55\x89\xE5\x81\xC3"; here, your string has a few NULL string terminator. This will NOT work with functions in <string.h> (such as strlen() and others)
Instead use memcpy, memset functions to append ONLY after knowing the length of the binary string.
Store your result in a character array, but don't assume it will work as a regular string because of your data.
your example[] char array is defined as const so you can not modify it.
1) You should get an eror in the compilation if you change your const char array in this way
example[2] ='R';
2) You should get a warning if you modify your const char array via memcpy or via strcpy
Change it to
char example[] = "\x4D\x5A\xE8\x00\x00\x00\x00\x5B\x52\x45\x55\x89\xE5\x81\xC3";
And you can not use strcpy because your character array contains x00 in the middle so this will affect the strcpy function. Because strcpy stop when it find x00 in the char array
example[] char array contains x00 in the middle, so to find the length of example[] with strlen will not work properly. For this case I suggest to use sizeof(example) instead.
Here after how you can make your copy:
char example[] = "\x4D\x5A\xE8\x00\x00\x00\x00\x5B\x52\x45\x55\x89\xE5\x81\xC3";
DWORD* example2 = "\xAA\xBB\xCC\xDD";
if (sizeof(example)>=sizeof(example2))
memcpy(example+sizeof(example)-sizeof(example2), example2, sizeof(example2));
Const variables can't be changed. This is by design. In the case of a c string, you can have the contents of the string const or the pointer to the string const.
Since you are defining it as a const character array, the pointer is implicitely const and the contents are explicitly const.
const char * const mystring = "hello"
In this case the first "const" tries to apply left (there is nothing), so it applies right (to the char type). So the string content may not change. The second const tries to apply left, so it makes the pointer itself const. That means that the mystring pointer must always point to where the "h" from "hello" in memory is.
So afterwards if I try:
mystring[0] = "y"
or
mystring = "gooodbye!"
They would not work. If you removed the first or second const respectively, they could be made to work.
The purpose of const allows you to say ahead of time "this variable cannot be modified". That means that if it is modified then there is a problem. Generally you should always use const with any variable that you do not want to be modified after instantiation.
You should never modify a constant including a constant array. If you want to change what you have above, create a copy of it and change the copy. As pointed out by RasmusKaj strcpy will not help you here as the source strings contains zero chars so maybe use memcpy for the creation of the copy.