I'm trying to learn ncurses, and I'm reading the terrific guide here, but the example at user pointers does not compile. I get this error when I try to compile.
menu.cpp: In function 'int main()':
menu.cpp:44: error: invalid conversion from 'void (*)(char*)' to 'void*'
menu.cpp:44: error: initializing argument 2 of 'int set_item_userptr(ITEM*, void*)'
menu.cpp:70: error: invalid conversion from 'void*' to 'void (*)(char*)'
Also, you probably need to add cstdlib and cstring for that to compile with strlen and calloc.
I don't know much about void pointers, so some help fixing the example would be very appreciated.
Thanks
From reading the manual page:
#include <menu.h>
int set_item_userptr(ITEM *item, void *userptr);
void *item_userptr(const ITEM *item);
DESCRIPTION
Every menu item has a field that can be used to hold application-specific data (that is, the menu-driver code leaves it alone). These functions get and set that field.
userptr is user-specific data that you should supply to set_item_userptr(). If you don't want to supply any data, you should supply NULL. Looks like you are calling set_item_userptr() with a pointer to a function as its second argument. It is not guaranteed that you can convert a function-pointer to void * and back portably, either in C or in C++ (C++ requires a cast when converting a void * to any other pointer type). Without knowing what you are trying to do, if you really need to pass a function pointer, you should cast it to the appropriate type:
int ret = set_item_userptr(item, reinterpret_cast<void *>(ptr));
void (*pf)(char*);
pf = reinterpret_cast<void (*)(char *)>(item_userptr(item));
but it's not guaranteed to work. You should do something else, like having a struct that contains the function pointer, and passing a pointer to the struct to set_item_userptr().
You are using a C++ compiler, so you will need to do:
set_item_userptr(my_items[i], (void *)func);
and again,
p = (void*)item_userptr(cur);
Related
So this is what my function declaration looks like:
void mdump(char* startAdrs, char* endAdrs);
In my code, here's how I'm calling it:
char f = 'f';
char d[200*sizeof(int)];
mdump(&d, &f);
The error I'm getting is:
invalid arguments 'Candidates are: void mdump(char*, char*)'
Why am I not able to call the mdump function properly?
Use of
mdump(&d, &f);
is a compiler error since &d evaluates to a char (*)[200*sizeof(int)]. That cannot be converted to a char*.
You may use
mdump(d, &f);
to get past the compiler error. However, judging by the names of the arguments of mdump, the second argument needs to be d+sizeof(d).
mdump(d, d+sizeof(d));
You should not pass the address of d because d already acts as a pointer pointing to the first element.
so you should do this:
mdump(d, &f);
d is an array. so just writing d itself indicates the address of the first element in the array. By using &d, you are sending pointer to the pointer to a char. But you need to send pointer to a char. So the write way to call mydump is:
mdump(d, &f);
I have a function like this:
void getSprite(string *spriteLines[SPRITE_YSIZE]);
And then I have a calling to the function like this:
int main() {
string *spriteLines[SPRITE_YSIZE];
getSprite(spriteLines);
By here, everything OK. But I decided to declare spriteLines as a string instead of a pointer so I changed the code to this:
int main() {
string spriteLines[SPRITE_YSIZE];
getSprite(&spriteLines);
And an error shows up:
error: cannot convert ‘std::__cxx11::string (*)[5] {aka std::__cxx11::basic_string<char> (*)[5]}’ to ‘std::__cxx11::string** {aka std::__cxx11::basic_string<char>**}’ for argument ‘1’ to ‘void getSprite(std::__cxx11::string**)’ getSprite(&spriteLines);
Do someone of you knows why? I can't understand this.
Extra data: I'm using Eclipse Oxygen v1 and GNU G++.
In the first example, you declared an array of string pointers. In the second example you declared an array of strings. Both arrays are passed your function as a pointer. Your error occurs because the are different "types".
In the second example you would need to change your getSprite function to:
void getSprite(string spriteLines[SPRITE_YSIZE])
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?
I am trying to get fingerprint data (which I created and stored as a text file in another code) which I have to compare with a new fingerprint in this code. The problem is that the fingerprint API requires the fingerprint data to be passed as char pointer. I'm using the following code :
std::ifstream infile("timestamp.txt");
char* text_stream;
std::string line;
if (infile.is_open()){
while ( getline (infile,line)){
if(text_stream){
*text_stream = malloc (1 + strlen (line));
strcpy(text_stream,line);
}
else{
fprintf (stderr, "malloc failure!");
}
}
infile.close();
}
I have also tried using other codes for the same purpose but I'm getting this kind of compilation error everytime:
verifiy.cpp: In function ‘int main()’:
verifiy.cpp:29:47: error: cannot convert ‘std::string {aka std::basic_string<char>}’ to ‘const char*’ for argument ‘1’ to ‘size_t strlen(const char*)’
*text_stream = malloc (1 + strlen (line));
^
verifiy.cpp:30:31: error: cannot convert ‘std::string {aka std::basic_string<char>}’ to ‘const char*’ for argument ‘2’ to ‘char* strcpy(char*, const char*)’
strcpy(text_stream,line);
^
BTW, if you are just reading the whole file, you can write something like this:
#include <string>
#include <fstream>
#include <streambuf>
std::ifstream t("timestamp.txt");
std::string str((std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>());
(If you care about the efficiency of the code above, there is a more efficient version here: Read whole ASCII file into C++ std::string)
That way, you don't need to create an explicit string buffer yourself. After that, you can just use str.c_str() to get a "const char*".
While using that, please beware that the resulting pointer can be invalid if you keep editing the string. In that case, you might need to make another copy of the string. If your function needs a "char*" instead of a "const char*", you might need to do that too. More information can be found here: How to convert string to char array in C++?
You actually have two errors in the code, first the one you show in your question (it's the same error in two different places), the second error is worse and will lead to undefined behavior.
The first error is that std::string is not a char*, so you can't use the old C functions with it. Reading this reference should help you a little.
The second problem is that text_stream is a pointer to char, meaning *text_stream will give you what text_stream points to, i.e. a single char, or text_stream[0]. This is problematic because of two reasons: The first because text_stream is uninitialized, its contents is indeterminate and dereferencing will not give you a valid pointer leading to undefined behavior. The second problem with that is that *text_stream is not a pointer, assigning to *text_stream will not change text_stream so text_stream will still be uninitialized while you overwrite some random memory. If the compiler doesn't shout warnings at you for this assignment, then you need to enable more warnings. Warnings from the compiler are just as important as compiler errors, and they often indicate places you do something which is not technically wrong but will lead to other problems when running the program.
The solution to both these problems is to stop using C function in C++. Use std::string exclusively, and when you need to call a function which needs a const char * argument, just use std::string::c_str to get such a pointer.
This gives the error: cannot convert from 'const char *' to 'char *'.
class Mock
{
public:
...
static void func(char **result)
{
*result = (resultsI++)->c_str();
}
static std::vector<std::string> results;
static std::vector<std::string>::iterator resultsI;
};
std::vector<std::string> Mock::results;
std::vector<std::string>::iterator Mock::resultsI;
How can I validly get rid of this error without changing the interface to the function func? The implementer of this interface:
void (func*)(char **result)
forgot to use const char** in the signature. I can't change it.
Remember this is a mock and I'm only used in my unit tests.
Try:
*result = &(*resultsI++)[0];
Although this isn't guaranteed to work prior to C++11 it is known to be OK on most or all current compilers.
The danger is that if the function tries to change the length of the string, you could get some nasty errors. Changing individual characters should be OK.
In test code, and if you are certain that the user of the interface isn't going to mutate the char*, maybe you could use a const_cast?
That assumes the caller doesn't take ownership of the char *; if that is the case, then you should make a copy.
If you're absolutely certain that the interface function will not modify the string, you can use
*result = const_cast<char *>((resultsI++)->c_str());
to remove constness.
Otherwise, another option is to switch from using std::vector<std::string> to std::vector<std::vector<char>> but then you'll have to make sure you properly null terminate the strings.