Description:
Declaration of strstr:
char *strstr(const char *haystack, const char *needle);
Definition of my function:
hostinfo_t *extract_host_from_url(const char *url) {
/* ... */
char *scheme_pos = strstr(url, "://");
/* ... */
}
How I use it:
void rewrite_url(string &url) {
/* ... */
hostinfo_t * hostinfo = extract_host_from_url(url.c_str());
/* ... */
}
Error info:
error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
char *scheme_pos = strstr(url, "://");
Question:
Where do things go wrong?
C++ declaration of strstr, as given in <cstring> is overloaded
const char* strstr( const char* str, const char* target );
char* strstr( char* str, const char* target );
With your set of arguments, you are calling the first function, which is why the return type is const char*.
Related
aa.h
#ifndef __US_LOG_FILEA_H_
#define __US_LOG_FILEA_H_
namespace AA{
class A{
public:
A();
~A();
static A& Ins(){
static A obj;
return obj;
}
void do_p(const char *cat, int level, const char *Format ...); // ok
void do_p(const char *cat, int level, const char *Format, ...); // error
};
} // namespace AA
extern AA::A g_A;
#endif // __US_LOG_FILEA_H_
formatstr.cpp
void test()
{
g_A.do_p("global func", 2, "%s\n", str);
}
a.cfg:
<?xml version="1.0"?>
<def>
<function name="AA::A::do_p">
<noreturn>false</noreturn>
<leak-ignore/>
<formatstr type="printf"/>
<arg nr="3">
<formatstr/>
<not-uninit/>
</arg>
</function>
</def>
cppcheck --enbale-style --library=a.cfg formatstr.cpp
if void do_p(const char *cat, int level, const char *Format ...); cppcheck output:
warning: %s in format string (no. 1) requires 'char *' bu
t the argument type is 'std::string'. [invalidPrintfArgType_s]
g_A.do_p("global func", 2, "%s\n", str);
but do_p(const char *cat, int level, const char *Format,...); cppcheck output nothing
WHY?
The Cppcheck's version is 1.89.0.0
Thanks in advance.
WHY?
void do_p(const char *cat, int level, const char *Format ...); // ok
Presumably because cppcheck doesn't recognise const char *Format ... as a printf format and variadic arguments unless they are separated by comma, so you didn't get the error.
void do_p(const char *cat, int level, const char *Format, ...); // error
You configured cppcheck to check bad format / argument pairing, so this is where you should expect an error.
1st, modify the Cpp member function code to C-style function
2nd, remove overload funcions
I have defined the following structure:
struct com_NetworkStruct
{
enum com_NetworkStatus status;
char IPV4_Addr[COM_IPV4_ADDR_LENGTH];
char IPV4_Netmask[COM_IPV4_ADDR_LENGTH];
char IPV4_DNS1[COM_IPV4_ADDR_LENGTH];
char IPV4_DNS2[COM_IPV4_ADDR_LENGTH];
int IPV4_DHCP_Enabled;
int IPV6_Supported;
int IPV6_Enabled;
struct com_IPv6_Data *IPV6_Address_List;
char HW_Addr[COM_ETH_MAC_ADDR_LENGTH];
int MTU_Size;
int Link_Speed;
enum com_LinkType Link_Type;
};
And the following method definition:
int foo(struct com_NetworkStruct **netinfo);
This is the main function and how i call the function:
int main(int argc, char const *argv[])
{
int ret;
char data_aux[200];
struct com_NetworkStruct *netinfo = NULL;
ret = foo(&netinfo);
memset(data_aux, 0, sizeof(data_aux));
sprintf(data_aux, "%s", netinfo->IPV4_Addr);
cout<<string(data_aux)<<endl;
return 0;
}
The problem is when I try to read the data of the IPV4_Addr value since it sends me the following error:
Error: #289: no instance of constructor "std::basic_string<_CharT, Traits, Alloc>::basic_string [with CharT=char, Traits=std::char_traits<char>, _Alloc=std::allocator<char>]" matches the argument list
argument types are: (const char [20], char [16])
I already tried this, but nothing works:
&netinfo->IPV4_Addr
netinfo.IPV4_Addr
string(netinfo->IPV4_Addr)
A simple C++ code:
int main(){
unsigned char* t="123";
}
on compilation with g++ gives following error:
invalid conversion from ‘const char*’ to ‘unsigned char*’ [-fpermissive]
Why?
In C++ string literals have types of constant character arrays. For example string literal "123" has type const char[4].
In expressions with rare exceptions arrays are converted to pointers to their first elements.
So in this declaration
unsigned char* t="123";
the initializer has type const char *. There is no implicit conversion from const char * to unsigned char *
You could write
const unsigned char* t = reinterpret_cast<const unsigned char *>( "123" );
Another approach, which gets you a modifiable unsigned char array as you originally wanted, is:
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
int main()
{
unsigned char ta[] = "123";
unsigned char* t = ta;
cout << t << endl; // Or ta.
return EXIT_SUCCESS;
}
You can add const to both declarations if you wish, to get const unsigned char without an explicit cast.
Simply use
just char* in place of unsigned char* during declaration
char t[MAX_SIZE] = "123"; // MAX_SIZE should be defined earlier
time tested strcpy() and strncpy functions
Conversions from one type to another type is easy when you use self-defined macros. So here is a set of macros you can use across any platform (Windows, Linux, Solaris, AIX etc...)
#define M_ToCharPtr(p) reinterpret_cast<char*>(p) // Cast to char*
#define M_ToWCharPtr(p) reinterpret_cast<wchar_t*>(p) // Cast to wchar_t*
#define M_ToConstCharPtr(p) reinterpret_cast<const char*>(p) // Cast to const char*
#define M_ToConstWCharPtr(p) reinterpret_cast<const wchar_t*>(p) // Cast to const wchar_t*
#define M_ToUCharPtr(p) reinterpret_cast<unsigned char*>(p) // Cast to unsigned char*
#define M_ToConstUCharPtr(p) reinterpret_cast<const unsigned char*>(p) // Cast to const unsigned char*
#define M_ToUCharPtr(n) reinterpret_cast<unsigned char*>(n) // Cast to unsigned char*
#define M_ToVoidPtr(p) reinterpret_cast<void*>(p) // Cast to void*
#define M_ToConstVoidPtr(p) reinterpret_cast<const void*>(p) // Cast to const void*
#define M_ToIntPtr(n) reinterpret_cast<int*>(n) // Cast to int*
#define M_ToConstIntPtr(p) reinterpret_cast<const int*>(p) // Cast to const int*
#define M_ToDoublePtr(n) reinterpret_cast<double*>(n) // Cast to double*
#define M_ToConstDoublePtr(n) reinterpret_cast<const double*>(n) // Cast to const double*
#define M_ToBoolPtr(n) reinterpret_cast<bool*>(n) // Cast to bool*
#define M_ToConstBoolPtr(n) reinterpret_cast<const bool*>(n) // Cast to const bool*
// General Cast
#define M_To(T, p) reinterpret_cast<T>(p) // Cast to T
In your case
const unsigned char* t = reinterpret_cast<const unsigned char *>("UCHAR TO CONST UCHAR");
is equivalent to
const unsigned char* t = M_ToConstUCharPtr("UCHAR TO CONST UCHAR");
I am creating an Apache2 module and experiencing a weird compilation problem.
This is prototype of my function used to parse config command named "analytics_ip":
static const char *apr_cfg_set_analytics_ip(cmd_parms *cmd, void *config, const char *data);
This is array of command_rec structures containing pointers to this function:
static const command_rec apr_cmds[] =
{
AP_INIT_TAKE1("analytics_ip", apr_cfg_set_analytics_ip, NULL, OR_ALL, ""),
{ NULL }
};
Structure command_rec is declared in header file http_config.h
typedef struct command_struct command_rec;
struct command_struct {
/** Name of this command */
const char *name;
/** The function to be called when this directive is parsed */
cmd_func func;
/** Extra data, for functions which implement multiple commands... */
void *cmd_data;
/** What overrides need to be allowed to enable this command. */
int req_override;
/** What the command expects as arguments */
enum cmd_how args_how;
/** 'usage' message, in case of syntax errors */
const char *errmsg;
};
When I follow cmd_func, it gets to the following declaration:
typedef const char *(*cmd_func) ();
If I am not mistaken, this means "pointer to function returning pointer to char and not accepting any arguments". How can this be possible? Command parsing function has to accept at least one parameter containing a module value of config variable corresponding to that function.
I am using g++ to compile this module.
Error message:
mod_xxx.h:65:2: error: invalid conversion from ‘const char* (*)(cmd_parms*, void*, const char*) {aka const char* (*)(cmd_parms_struct*, void*, const char*)}’ to ‘cmd_func {aka const char* (*)()}’ [-fpermissive]
};
Thanks in advance
cmd_func is a union, it is defined in http_config.h as follows:
typedef union {
/** function to call for a no-args */
const char *(*no_args) (cmd_parms *parms, void *mconfig);
/** function to call for a raw-args */
const char *(*raw_args) (cmd_parms *parms, void *mconfig,
const char *args);
/** function to call for a argv/argc */
const char *(*take_argv) (cmd_parms *parms, void *mconfig,
int argc, char *const argv[]);
/** function to call for a take1 */
const char *(*take1) (cmd_parms *parms, void *mconfig, const char *w);
/** function to call for a take2 */
const char *(*take2) (cmd_parms *parms, void *mconfig, const char *w,
const char *w2);
/** function to call for a take3 */
const char *(*take3) (cmd_parms *parms, void *mconfig, const char *w,
const char *w2, const char *w3);
/** function to call for a flag */
const char *(*flag) (cmd_parms *parms, void *mconfig, int on);
} cmd_func;
enum cmd_how args_how; is responsible for choosing the correct version of the function.
The switch handling it is located in server/config.c (in the invoke_cmd function).
You seem to be using the "take1" version which corresponds to cmd->AP_TAKE1 or simply cmd->take1.
The problem might be that C and C++ have differences regarding the union initialization. (AP_INIT_TAKE1 uses the { .take1=func } syntax which doesn't work in C++).
You'll have to initialize static const command_rec apr_cmds in a C++-compatible way or move it to a separate object file compiled with C. Or if you're not using C++ then simply compile with gcc.
For the project I'm working on we ended up adding a cast to allow the compilation to complete successfully, and the code seems to work OK as it correctly reads in the values specified in the configuration file. Here's the extract of this practice:
extern "C" {
static const command_rec kiwix_settings[] =
{
AP_INIT_TAKE1("zimFile", (const char* (*)())kiwix_set_zimfilename, NULL, RSRC_CONF, "The ZIM filename in full including the extension"),
AP_INIT_TAKE1("zimPath", (const char* (*)())kiwix_set_path, NULL, RSRC_CONF, "The path to the ZIM file, including the trailing //"),
{ NULL }
};
}
The full file (and indeed the project) are opensourced. Here's the link to the full file https://github.com/kiwix/kiwix-apache/blob/master/mod_kiwix.cpp
PS: thanks for your question and https://stackoverflow.com/users/257568/artemgr's answer as they helped me and another volunteer to work out how to resolve the problem for our project.
Ok, I am trying to compile a program:
g++ -std=c++0x a1test.cpp GS1Prefix.cpp EAN.cpp
But I am getting errors that I never seen before.
In file included from a1test.cpp:17:0:
EAN.h:3:25: error: âPrefixâ does not name a type
EAN.h:3:33: error: ISO C++ forbids declaration of âpâ with no type [-fpermissive]
a1test.cpp: In function âbool RegisteredTests(const Prefix*, int&, int*, int*)â:
a1test.cpp:222:68: error: no matching function for call to âisRegistered(const Prefix*&, const char [14], char [6], char [8], char [7])â
a1test.cpp:222:68: note: candidates are:
EAN.h:3:6: note: bool isRegistered(const int*, const char*, char*, char*, char*)
EAN.h:3:6: note: no known conversion for argument 1 from âconst Prefix*â to âconst int*â
GS1Prefix.h:10:6: note: bool isRegistered(const Prefix*, int)
GS1Prefix.h:10:6: note: candidate expects 2 arguments, 5 provided
This is just half of the errors, below i have all the .h files and a link to a1test.cpp (its a long code)
EAN.h
bool isValid(const char* str);
bool isRegistered(const Prefix* p, const char* str, char area[],char publisher[], char title[]);
GS1Prefix.h
const int MAX = 700;
struct Prefix {
int no; // number of entries
int area[MAX]; // area elements
char pubLow[MAX][8]; // low end of publisher range
char pubHgh[MAX][8]; // high end of publisher range
int pubLen[MAX]; // no of chars in publisher string
};
bool load(const char* filename, Prefix* p);
bool isRegistered(const Prefix* p, int area);
int minNoDigits(const Prefix* p, int area);
bool isRegistered(const Prefix* p, int area, const char* publisher);
Link to a1test.cpp ->a1test.cpp
UPDATE: As suggested by remyabel, i made #include "GS1Prefix.h" after #include "EAN.h"
In file included from EAN.cpp:6:0:
EAN.h:3:25: error: âPrefixâ does not name a type
EAN.h:3:33: error: ISO C++ forbids declaration of âpâ with no type [-fpermissive]
Simply switch the order of your headers and your code should compile fine. Because you did not provide GS1Prefix.cpp and EAN.cpp I cannot comment on the rest of the errors (if there are any left.)
#include <cstring>
// GS1Prefix.h
const int MAX = 700;
struct Prefix {
int no; // number of entries
int area[MAX]; // area elements
char pubLow[MAX][8]; // low end of publisher range
char pubHgh[MAX][8]; // high end of publisher range
int pubLen[MAX]; // no of chars in publisher string
};
// EAN.h
bool isValid(const char* str);
bool isRegistered(const Prefix* p, const char* str, char area[],char publisher[], char title[]);
// a1test.cpp
bool load(const char* filename, Prefix* p);
bool isRegistered(const Prefix* p, int area);
int minNoDigits(const Prefix* p, int area);
bool isRegistered(const Prefix* p, int area, const char* publisher);
// .. rest of your file
Header files should include sufficient definition so that they are self-sufficient. In this case you need to supply a definition of the requisite type, Prefix. Just add the include to the top of EAN.h:
#include <GS1Prefix.h>
bool isValid(const char* str);
bool isRegistered(const Prefix* p, const char* str, char area[],char publisher[],
char title[]);
Then you can include EAN.h in any source file knowing that you don't have dependencies to worry about.