Anywhere I can find some documentation of MiniUPnP?
For example, some doc explains what the parameters of this function are.
LIBSPEC int
UPNP_AddPortMapping(const char * controlURL, const char * servicetype,
const char * extPort,
const char * inPort,
const char * inClient,
const char * desc,
const char * proto,
const char * remoteHost,
const char * leaseDuration);
theses are methods defined by UPnP standard.
Have a look at http://upnp.org/specs/gw/UPnP-gw-WANIPConnection-v2-Service.pdf
for UPNP_AddPortMapping.
To see more specificaly how to use with libminiupnpc, see the upnpc.c sample program.
https://github.com/miniupnp/miniupnp/blob/master/miniupnpc/upnpc.c
Related
I am reading application code developed in the IBM RSARTE C++ version. Here is a piece of C++ code:
const char * const * av = RTMain::argStrings();
How to understand the left-hand side syntax when there are two const and two *?
const char * const * av = RTMain::argStrings();
is the same as
char const * const * av = RTMain::argStrings();
const applies to what's left of const.
So, av is a non-const pointer to a const* to const char.
The returned pointer, av, is non-const and can be changed.
The pointer av is pointing at is const and can not be changed.
The char that pointer is pointing at is const and can not be changed.
Read this declaration
const char * const * av
from right to left. There is declared the pointer av ( * av ) that points to a constant pointer ( * const ) that in turn points to an object of the type const char.
To simplify this declaration consider this code snippet.
const char *literal = "Hello World!";
const char * const * pointer_to_the pointer_literal = &literal;
So using the pointer pointer_to_the pointer_literal you may not write for example
*pointer_to_the pointer_literal = "Bye";
and you may not write
**pointer_to_the pointer_literal = 'h';
Sometimes using pure-C libs in my C++ projects, I see strange (in my opinion) function declarations.
E.g.: libldap's ldap_search_ext(): https://linux.die.net/man/3/ldap_search_ext_s
int ldap_search_ext(
LDAP *ld,
char *base,
int scope,
char *filter,
char *attrs[], // this one!
int attrsonly,
LDAPControl **serverctrls,
LDAPControl **clientctrls,
struct timeval *timeout,
int sizelimit,
int *msgidp );
Why can't attrs[] be a const char *?
Declarations like this don't want to change the content of the pointer and generate a lot of issues:
// pure C
void func(char * data[])
{
...
}
func({"blabla"}); // won't work (corrected: yes, this is wrong syntax, but it's true for structs of pointers)
const char *d[] = {"blabla", "blablu"};
func(d); // won't work
// C++
const std::string str("blabla");
char * data[] = { str.data() }; // even non-const won't work (because data() returns const*)
/// etc...
Is there any reason for not declaring such arguments as const?
This is mostly just (due to) a historical wart in the C standard that has never been fixed.
When const was added to C, the ability to implictly (and safely) convert simple pointers was added -- you can implicitly convert a T * to a const T * just fine. However, (safe) conversion of more complex pointer types was missed -- you can't convert a T * const * to a const T * const *. As a result, when a library takes a double pointer like this, it does not have any 'good' way of making it const if it is read only. Making it either a const char ** or a const char * const * would break some uses (requiring messy explicit casts).
Note that allowing implicit conversions of T ** to const T ** would be unsafe -- such a pointer could be used to modify a T * to point at a const T * without a cast.
One likely reason is that string constants in C (unlike C++) are not const.
As such, there was a historical lack of const-correctness in many libraries that should have been there. Had string constants been const, programmers would have been forced to account for it.
When dealing with libraries such as this that you know don't modify the argument, you have to apply a const_cast to make it fit.
char *d[] = {const_cast<char *>("blabla"), const_cast<char *>("blablu")};
func(d);
const std::string str("blabla");
char * data[] = { const_cast<char *>(str.data()) };
func(data);
I want to create my own string storage (class) and I know something about const char * and char *.
This is a part of my source:
class str_n
{
private:
char * _str;
public:
str_n(const char * str)
{
std::size_t Read_len = strlen(str);
_str = (char *) malloc(Read_len + 1);
memcpy(_str, str, Read_len + 1);
}
};
I used char * and const char * for my _str and I know if I use const char * I need to copy it to char * whlie I want to use some other functions inside of my class and also using const char * is faster (very faster (about 2x)) than char * to save the const char * param content.
Now my question: If you want to create new string storage, you use const char * or char *?
Use char *, if your str_n is mutable. You're wrong on the part that const content is modifiable. For example, this:
const char *foo = "foo";
foo[0] = 'a';
won't compile. Trying to circumvent it with const_cast is not a viable option:
const_cast<char *>(foo)[0] = 'a';
as it is undefined behavior, and usually crashes, as foo is put in read-only memory.
So, if your string is mutable, you must copy the contents of str (the parameter for the constructor) in your example (you don't have the option of using const char * as storage, and omitting the copy to make your program faster -- I suppose you meant "2x faster" because you omitted the copy).
A note: you should use new instead of malloc, it is more c++-ish (you won't need to cast to char * the result of new char[...])
Just use std::string
class str_n {
public:
str_n(const char * str_in) : str{str_in} {}
private:
std::string str;
};
you can fetch the c string from a C++ string with the .c_str() method
For reading complex pointer declarations there is the right-left rule.
But this rule does not mention how to read const modifiers.
For example in a simple pointer declaration, const can be applied in several ways:
char *buffer; // non-const pointer to non-const memory
const char *buffer; // non-const pointer to const memory
char const *buffer; // equivalent to previous declartion
char * const buffer = {0}; // const pointer to non-const memory
char * buffer const = {0}; // error
const char * const buffer = {0}; // const pointer to const memory
Now what about the use of const with a pointer of pointer declaration?
char **x; // no const;
const char **x;
char * const *x;
char * * const x;
const char * const * x;
const char * * const x;
const char * const * const x;
And what is an easy rule to read those declarations?
Which declarations make sense?
Is the Clockwise/Spiral Rule applicable?
Two real world examples
The method ASTUnit::LoadFromCommandLine uses const char ** to supply command line arguments (in the llvm clang source).
The argument vector parameter of getopt() is declared like this:
int getopt(int argc, char * const argv[], const char *optstring);
Where char * const argv[] is equivalent to char * const * argv in that context.
Since both functions use the same concept (a vector of pointers to strings to supply the arguments) and the declarations differ - the obvious questions are: Why do they differ? Makes one more sense than the other?
The intend should be: The const modifier should specify that the function does not manipulate strings of this vector and does not change the structure of the vector.
The const modifier is trivial: it modifies what precedes it, unless
nothing precedes it. So:
char const* buffer; // const modifies char
char* const buffer; // const modifies *
, etc. Generally, It's best to avoid the forms where nothing precedes
the const, but in practice, you're going to see them, so you have to
remember that when no type precedes the const, you have to logically
move it behind the first type. So:
const char** buffer;
is in fact:
char const** buffer;
, i.e. pointer to pointer to const char.
Finally, in a function declaration, a [] after reads as a * before.
(Again, it's probably better to avoid this misleading notation, but
you're going to see it, so you have to deal with it.) So:
char * const argv[], // As function argument
is:
char *const * argv,
a pointer to a const pointer to a char.
(Trying to focus on other aspects of the question)
The rule of thumb for const declarations is to read them from right to left and const modifies the next token. Exception: At the beginning of a declaration const modifies the previous token.
There is a rationale behind this exception - for elementary declarations const char c looks for some people more natural than char const c - and it is reported that a precursor form of const char c predates the final const rule.
getopt
int getopt(int argc, char * const argv[], const char *optstring);
or
int getopt(int argc, char * const * argv, const char *optstring);
Which means that argv is a pointer to const vector of pointers to non-const strings.
But one would expect following declaration:
int getopt(int argc, char const * const * argv, const char *optstring);
(pointer to const vector to const strings)
Because getopt() is not supposed to change the strings referenced via argv.
At least char ** (as used in main()) automatically converts to char * const * argv.
Clang
ASTUnit::LoadFromCommandLine(..., const char **argv, ...);
Which means that argv is a pointer to a non-const array of pointers to const strings.
Again one would expect const char * const *argv for the same reason as above.
But this is more noticeable because char ** does not convert to const char **, e.g.
int main(int argc, char **argv) {
const char **x = argv; // Compile error!
return 0;
}
yields a compile error, where
int main(int argc, char **argv) {
char * const *x = argv;
return 0;
}
and
int main(int argc, char **argv) {
const char * const *x = argv;
return 0;
}
do not.
I have a function with signature like this:
void foo(const std::vector<std::string>& args)
{
...
}
I want convert vector args to const char ** (just like argv in main). How this can be done? We can't actually make a char ** array because then it (obviously) fails to convert args[i].c_str() that is of type const char * to char *.
The only (ugly) way I can think of is to use const_cast to cast from const char * to char *.
Would anyone suggest more elegant way of doing this? I should note I can use only c++03 features.
Thanks in advance.
It can't be done without an extra array. A const char** means "a pointer to a pointer to const char" - so you need a place where there are actual pointers to char to point to.
So you need to create that array.
struct c_str { const char* operator ()(const std::string& s) { return s.c_str(); } };
std::vector<const char*> pointers(args.size());
std::transform(args.begin(), args.end(), pointers.begin(), c_str());
// If you really want to be compatible with argv:
pointers.push_back(0);
// &pointers[0] is what you want now