Could you please explain why, in order to convert a char array like this:
char strarr[5] = {65,83,67,73,73}; //ASCII
Into LPCSTR to be accepted by GetModuleHandleA() and GetProcAddress(), I have to first append 0 to the end ?
i.e. I have:
char strarr[6] = {65,83,67,73,73,0};
And only then convert as (LPCSTR)&strarr.
For some reason I don't get the first one works only sometimes (i.e. if I do not add 0 at the end), while if I do add zero at the end - this work all the time. Why do I have to add zero?
Oh and a side question - why in C++ do I have to explicitly state the size of array in [], when I am initializing it with elements right away? (If I don't state the size, then it does not work)
Thanks.
Those functions expect NULL terminated strings.
Since you only give them a pointer to a char array, they can't possibily know its size, hence the need for a particular value (the terminating NULL character) to indicate the end of the string.
Related
This can be marked solved. The problem was the print macro. ESP_LOGx can't put out c++ Strings.
I'm trying to convert an uin8_t array to a string in c++.
The array is defined in a header file like this:
uint8_t mypayload[1112];
Printing the array itself works, so I'm sure it's not empty.
now I'm trying to convert it to a string:
string qrData;
std::string qrData(reinterpret_cast<char const*>(mypayload), sizeof mypayload);
I also tried:
qrData = (char*)mypayload;
printing the string results in 5 random chars.
Does anybody have hint where I made a mistake?
The only correct comment so far is from Some programmer dude. So all credits go to him.
The comment from Ian4264 is flat wrong. Of course you can do a reinterpret_cast.
Please read here about the constructors of a std::string. You are using constructor number 4. The description is:
4) Constructs the string with the first count characters of character string pointed to by s. s can contain null characters. The length of the string is count. The behavior is undefined if [s, s + count) is not a valid range.
So, even if the string contains 0 characters, the C-Style string-"terminator", all bytes of the uint8_t arrays will be copied. And if you print the string, then it will print ALL characters, even the none printable characters after the '\0'.
That maybe your "random" characters. Because the string after your "terminator" does most probably contain uninitialized values.
You should consider to use the constructor number 5
5) Constructs the string with the contents initialized with a copy of the null-terminated character string pointed to by s. The length of the string is determined by the first null character. The behavior is undefined if [s, s + Traits::length(s)) is not a valid range.
And if you need to add bytes, also possible. The std::string can grow dynamically.
BTW: you do define your "std::string qrData" double, which will not compile
Since you know the size of your data in another variable, why are you using sizeof? It will give you the size of the array, not the size of your data.
This should give you the right result, assuming no other errors in your code
std::string qrData(reinterpret_cast<char const*>(mypayload), data->payload_len);
Incidentally in the code you quoted why is qrData declared twice? That seems a bit suspicious.
qrData = (const char*)mypayload;
string is accept only const char*.
String s = String((char *)data, len); //esp32
I am working with snmp and the requests->requestvb->val.string function returns me a u_char* and I am trying to store that into a char[255].
u_char newValue = *(requests->requestvb->val.string)
char myArray[255];
I have tried a few approaches to copy the contents of newValue into myArray but everything seems to segfault. What am I doing wrong?
I have tried
memcpy(myArray, newValue);
Another attempt strncopy(myArray, newValue, sizeof(myArray));
What am I doing wrong?
Your newValue is of type char, and for all intents and purposes, your myArray is of type char*.
First off, I'm going to assume that you're using memcpy correctly, and that you're passing in 3 parameters instead of 2, where the 3rd parameter is the same as the one you use in strncpy.
When you try using strncpy or memcpy, you're going beyond the one character "limit" in newValue when attempting to copy everything to myArray.
The fix should be quite simple:
u_char* newValue = requests->requestvb->val.string;
Once you've done that, this should work. Of course, that's assuming that the size of myArray is in fact greater than or equal to 255 :)
As a side note (and this should go without saying), please make sure that your myArray has a null terminating character at the end if you ever plan on printing it. Not having one after performing copy operations, and then trying to print is a very common mistake and can also lead to seg faults.
I wrote the following code:
char *pch=new char[12];
char *f=new char[42];
char *lab=new char[20];
char *mne=new char[10];
char *add=new char[10];
If initially I want these arrays to be null, can't I do this:
*lab="\0";
*mne="\0";
and so on.....
And after that if I want to add some cstring to an empty array can't I check:
if(strcmp(lab,"\0")==0)
//then add cstring by *lab="cstring";
And if I can't do any of these things, please tell me the right way to do it...
In C++11, an easy way to initialize arrays is by using brace-initializers:
char * p = new char[100] { 0 };
The reasoning here is that all the missing array elements will be zero-initialized. You can also use explicit value-initialization (I think that's even allowed in C++98/03), which is zero-initalization for the primitive types:
char * q = new char[110]();
First of all, as DeadMG says, the correct way of doing this is using std:string:
std::string lab; // empty initially, no further initialization needed
if (lab.size() == 0) // string empty, note, very fast, no character comparison
lab += "cstring"; // or even lab = "cstring", as lab is empty
Also, in your code, if you insist in using C strings, after the initialization, the correct checking for the empty string would be
if (*lab == '\0')
First of all, I agree with everybody else to use a std::string instead of character arrays the vast majority of the time. Link for help is here: C++ Strings Library
Now to directly answer your question as well:
*lab="\0";
*mne="\0";
and so on.....
This is wrong. Assuming your compiler doesn't give you an error, you're not assigning the "null terminator" to those arrays, you're trying to assign the pointer value of where the "\0" string is to the first few memory locations where the char* is pointing to! Remember, your variables are pointers, not strings. If you're trying to just put a null-character at the beginning, so that strlen or other C-string functions see an "empty" string, do this: *lab='\0'; The difference is that with single-ticks, it denotes the character \0 whereas with double, it's a string literal, which returns a pointer to the first element. I hope that made sense.
Now for your second, again, you can't just "assign" like that to C-style strings. You need to put each character into the array and terminate it correctly. Usually the easiest way is with sprintf:
sprintf(lab, "%s", "mystring");
This may not make much sense, especially as I'm not dereferencing the pointer, but I'll walk you through it. The first argument says to sprintf "output your characters to where this pointer is pointing." So it needs the raw pointer. The second is a format string, like printf uses. So I'm telling it to use the first argument as a string. And the 3rd is what I want in there, a pointer to another string. This example would also work with sprintf(lab, "mystring") as well.
If you want to get into C-style string processing, you need to read some examples. I'm afraid I don't even know where to look on the 'net for good examples of that, but I wish you good luck. I'd highly recommend that you check out the C++ strings library though, and the basic_string<> type there. That's typedef'd to just std::string, which is what you should use.
First, I'd like to say that I'm new to C / C++, I'm originally a PHP developer so I am bred to abuse variables any way I like 'em.
C is a strict country, compilers don't like me here very much, I am used to breaking the rules to get things done.
Anyway, this is my simple piece of code:
char IP[15] = "192.168.2.1";
char separator[2] = "||";
puts( separator );
Output:
||192.168.2.1
But if I change the definition of separator to:
char separator[3] = "||";
I get the desired output:
||
So why did I need to give the man extra space, so he doesn't sleep with the man before him?
That's because you get a not null-terminated string when separator length is forced to 2.
Always remember to allocate an extra character for the null terminator. For a string of length N you need N+1 characters.
Once you violate this requirement any code that expects null-terminated strings (puts() function included) will run into undefined behavior.
Your best bet is to not force any specific length:
char separator[] = "||";
will allocate an array of exactly the right size.
Strings in C are NUL-terminated. This means that a string of two characters requires three bytes (two for the characters and the third for the zero byte that denotes the end of the string).
In your example it is possible to omit the size of the array and the compiler will allocate the correct amount of storage:
char IP[] = "192.168.2.1";
char separator[] = "||";
Lastly, if you are coding in C++ rather than C, you're better off using std::string.
If you're using C++ anyway, I'd recommend using the std::string class instead of C strings - much easier and less error-prone IMHO, especially for people with a scripting language background.
There is a hidden nul character '\0' at the end of each string. You have to leave space for that.
If you do
char seperator[] = "||";
you will get a string of size 3, not size 2.
Because in C strings are nul terminated (their end is marked with a 0 byte). If you declare separator to be an array of two characters, and give them both non-zero values, then there is no terminator! Therefore when you puts the array pretty much anything could be tacked on the end (whatever happens to sit in memory past the end of the array - in this case, it appears that it's the IP array).
Edit: this following is incorrect. See comments below.
When you make the array length 3, the extra byte happens to have 0 in it, which terminates the string. However, you probably can't rely on that behavior - if the value is uninitialized it could really contain anything.
In C strings are ended with a special '\0' character, so your separator literal "||" is actually one character longer. puts function just prints every character until it encounters '\0' - in your case one after the IP string.
In C, strings include a (invisible) null byte at the end. You need to account for that null byte.
char ip[15] = "1.2.3.4";
in the code above, ip has enough space for 15 characters. 14 "regular characters" and the null byte. It's too short: should be char ip[16] = "1.2.3.4";
ip[0] == '1';
ip[1] == '.';
/* ... */
ip[6] == '4';
ip[7] == '\0';
Since no one pointed it out so far: If you declare your variable like this, the strings will be automagically null-terminated, and you don't have to mess around with the array sizes:
const char* IP = "192.168.2.1";
const char* seperator = "||";
Note however, that I assume you don't intend to change these strings.
But as already mentioned, the safe way in C++ would be using the std::string class.
A C "String" always ends in NULL, but you just do not give it to the string if you write
char separator[2] = "||". And puts expects this \0 at the ned in the first case it writes till it finds a \0 and here you can see where it is found at the end of the IP address. Interesting enoiugh you can even see how the local variables are layed out on the stack.
The line: char seperator[2] = "||"; should get you undefined behaviour since the length of that character array (which includes the null at the end) will be 3.
Also, what compiler have you compiled the above code with? I compiled with g++ and it flagged the above line as an error.
String in C\C++ are null terminated, i.e. have a hidden zero at the end.
So your separator string would be:
{'|', '|', '\0'} = "||"
Sounds easy, but I've got a bug and I'm not sure what's causing it?
nopunccount = 0;
char *ra = new char[sizeof(npa)];
while (nopunccount <= strlen(npa)) {
ra[nopunccount] = npa[strlen(npa) - nopunccount];
nopunccount++;
}
ra never gets a value into it and I have verified that npa has char values to provide within the nopunccount range.
Any help is appreciated // :)
nopunccountstarts as 0, so in the first iteration of the loop the character assigned to ra[0] is npa[strlen(npa)]. This is the terminating '\0' of that string. So the resulting string in ra starts with a '\0' and is therefore considered to be ending at that first byte by the usual string functions.
What does the declaration of npa look like? If it is a pointer, sizeof(npa) will be the size of a pointer, rather than the allocated size. If these are zero-terminated strings (also known as "C strings"), then use strlen, not sizeof. If these aren't strings, you need to track how much you allocated in a separate variable.
I have some other critiques of this code, possibly unrelated to your problem.
while (nopunccount <= strlen(npa)) {
strlen is an O(n) operation. This code will traverse the string npa in every loop iteration. It's best to only compute the length once.
ra[nopunccount] = npa[strlen(npa) - nopunccount];
Same problem here.