I would appreciate for some C++ expertize advice on this please. I have a Char array
<unsigned char ch1[100];>
data (ASCII code) gets filled in this ( max 6 or 8 array spaces and rest is empty). I want to process valid bits in the array only either converting them to Hex or again Char array. I tried
<memcpy (ch1,ch2,sizeof(ch1))>
but all garbage values are also copied..... :(
<strcpy gives me an error>
also number of bytes copied are dynamic ( 1 time :- 4; 2 time :- 6.....)
Do you know how many valid bytes do you have in your array? If yes, you can pass that number in as the 3rd argument of memcpy.
Otherwise you can zero-initialize the array and use strcpy which will stop on the first zero:
char ch1[100];
// zero out the array so we'll know where to stop copying
memset(ch1, 0, sizeof(ch1));
... data gets filled here ....
strcpy (ch2, ch1);
// zero out array again so we'll catch the next characters that come in
memset(ch1, 0, sizeof(ch1));
... life goes on ...
So only copy the chars that are actually initialized. You as a programmer are responsible for tracking what's initialized and what's not.
Related
I am recreating the string class using char arrays. My problem is, when I allocate memory for a larger array, it generates an array that is completely the wrong size.
For example:
int allocated = 4;
char * reservedString = new char[allocated];
cout << strlen(reservedString);
Instead of creating a character array of size 4, reservedString points to a character array with 14 spots containing random characters.
This is what the debug shows me. Reserved string is now the wrong size with a bunch of random characters in it. When I try to use strcpy or strcpy_s it is writing memory out of bounds because the new array sizes are wrong.
How can I create a char array with an unknown length, which is provided by a variable, that is right size.
I can not use the std::string class or std::vector.
When you are creating an object with the new operator, your data remains not initialized. The code you provide is basically an array of bytes.
The documentation about strlen says:
computes the length of the string str up to, but not including the terminating null character.
There is no null terminator here.
You should do:
int allocated = 4;
char * reservedString = new char[allocated]();
This will initialize your array and set all the elements to \0
strlen expects a null-terminated string, which means a string that ends in a null character (\0). You're passing to it a pointer pointing to newly allocated memory, which contains uninitialized values and reading it causes undefined behavior. So when strlen searches for a null character in order to determine the length of the string, stuff is going to go wrong.
You cannot determine the size of an array given only a pointer to it unless you know it's going to be terminated by a null character or something similar. So either properly initialize the array with a null-terminated string or keep track of the length yourself.
What is the difference between
char (CharBuff[50])[10];
and
char CharBuff[10][50];
My requirement is to have 10 character buffers, each of length 50 max (including null terminating character)
And, I would like to access the buffers as CharBuff[0], CharBuff[1] and so on.
char (CharBuff[50])[10];
declares CharBuff as a 50-element array of 10-element arrays of char. The parentheses are superfluous in this case.
char CharBuff[10][50];
declares CharBuff as a 10-element array of 50-element arrays of char.
Given that you want 10 strings of up to 50 characters, you would use the second form; the type of each CharBuff[i] will be "50-element array of char".
If you really wanted to create a separate type definition for a 50-element array of char, you could do something like
typedef char Str[50];
...
Str CharBuff[10];
Now CharBuff is a 10-element array of Str, which is a 50-element array of char.
Normally, I would not create a separate typedef like this unless I wanted to make Str opaque; that is, I don't want to expose the details of its implementation to whomever's using it. In addition to the typedef, I'd also supply an API for allocating, assigning, copying, formatting, and displaying objects of type Str.
Put another way, if the person using the Str type has to be aware that it's a 50-element array of char in order to use it properly, then it's better to just make them use a 50-element array of char.
The other answers here which say they're the same are wrong! Both are NOT the same arrays and their sizes are very different. Here's a snippet to show that:
char i[50][10];
std::cout << sizeof(i[1]) << '\n';
char (j[10])[50];
std::cout << sizeof(j[1]) << '\n';
10
50
You can see the live example here.
i is a 50-element array with each element being a 10-element array of characters, while j is a 10-element array with each element being a 50-element array of characters. Although the total sizes of both would be the same, the size of an element at each level would be different. If you assume they're the same, it would lead to undefined behaviour
i[25][5] // OK
j[25][5] // accessing j beyond index 9 is undefined behaviour!
This shows that the parenthesis have no significance in a non-pointer, non-reference array declaration i.e. char (j[10])[50] is just confusing notation for char j[10][50].
My requirement is to have 10 character buffers, each of length 50 max
Then you should declare your array as char CharBuff[10][50].
Nobody ever uses the former, always use the latter form:
char CharBuff[10][50];
Latter syntax will be proficient and less confusing as per you requirement of 10 rows (char buffers) having length of 50 each.
Go for the last one as it clearly states what you are allocating.
However, since the question is tagged with c++ too, I would advise using std::vector and std::string as it follows:
std::vector<std::string> CharBuff(10, std::string(50, '\0'));
The big problem that i see here is confusing syntax. When you use parenthesis they already have known roles in c and c++ syntax such as type conversions, pointers to functions(which looks a bit like what you wrote). What you are using them for add's a new meaning which makes code more obfuscated and ignores the fact that c and c++ have a great and intuitive way, for anybody that used matrices at least once, to express 2d arrays. So, for a clean and not confusing syntax use the latter version:
char CharBuff[10][50];
You are looking for 10 arrays of 50 chars each.
To declare a single buffer of 50 bytes, you would use
char CharBuff[50];
But you want to have 10 buffers, so just tack that on to before[50], e.g.:
char CharBuff[10][50];
Now CharBuff[0] will address the first fifty-byte buffer, CharBuff[1] will get the second, and so on.
If I write:
char lili [3];
cout<<strlen(lili)<<endl;
then what is printed is : 11
but if I write:
char lili [3];
lili [3]='\0';
cout<<strlen(lili)<<endl;
then I get 3.
I don't understand why it returns 11 on the first part?
Isn't strlen supposed to return 3, since I allocated 3 chars for lili?
It is because strlen works with "C-style" null terminated strings. If you give it a plain pointer or uninitialised buffer as you did in your first example, it will keep marching through memory until it a) finds a \0, at which point it will return the length of that "string", or b) until it reaches a protected memory location and generates an error.
Given that you've tagged this C++, perhaps you should consider using std::array or better yet, std::string. Both provide length-returning functions (size()) and both have some additional range checking logic that will help prevent your code from wandering into uninitialised memory regions as you're doing here.
The strlen function searches for a byte set to \0. If you run it on an uninitialized array then the behavior is undefined.
You have to initialize your array first. Otherwise there is random data in it.
strlen is looking for a string termination sign and will count until it finds it.
strlen calculates the number of characters till it reaches '\0' (which denotes "end-of-string").
In C and C++ char[] is equivalent to char *, and strlen uses lili as a pointer to char and iterates the memory pointed to by it till it reaches the terminating '\0'. It just so happened that there was 0 byte in memory 11 bytes from the memory allocated for your array. You could have got much stranger result.
In fact, when you write lili[3] = '\0'
you access memory outside your array. The valid indices for 3-element array in C/C++ are 0-2.
i wonder about int array in c affect to memory.
for example we opened char array char array[10];
it wont open 10 it'll open 11 because of '\0'
is there same situation on int array?
when we declare int abc[10]; will it open array that is 10 int size or 11 like char?
Thanks...
You are wrong with regards to char array[10]. This will not declare an array of 11 elements, only 10, including the terminating '\0'. This means that if you put a string of ten characters in the array, it will overflow.
some_type name[10] will always declare an array of 10 elements, never more, never less.
Any array declaration will have x number of elements
type array[x]
not x+1.
not even the char one.
read here more about arrays:
http://www.cplusplus.com/doc/tutorial/arrays/
I think declaring char array[10] allocates exactly 10 bytes of space, it is your job to manage memory with '\0' if you see fit.
int abc[10] creates an array of 10 ints, with subscripts 0 through 9. Changing the type (e.g., to char abc[10] doesn't change the number of items in the array.
With an array of char, the NUL terminator is considered part of the string, so if you provide an initializer and specify a size, the size must be at least as large as the size of the string including the NUL terminator. If you don't specify the size, the size will be the length of the string including the NUL terminator.
char a[] = "A string"; // sizeof(a)==9
Note, however, that C is slightly different in this respect -- in C you can specify an initializer and a size that does not include space for the NUL terminator, and it'll still compile.
char a[9] = "A string"; // allowed in either C or C++
char a[8] = "A string"; // allowed in C, but not C++.
I'm not sure what you mean by "opened" an array. If you declare:
char array[10];
you define an array of ten char. If you declare:
int array[10];
you define an array of ten int. Both uninitialized unless defined
with static lifetime.
The appended '\0' only affects string literals and initialization
strings.
for example we opened char array char array[10]; it wont open 10 it ll open 11 because of '\0'
Wrong. In C, you are expected to take care of your terminating \0's in strings - the compiler won't do any favour for you. If you declare a char[10], you get exactly 10 chars, and the same is true for ints and all other types.
A char array[10] will create an array of 10 elements. I think you are a bit confused because in c typically you have to create an array of size 11 to store a word of size 10, because you need to have one extra element for the '\0' char in the end. But still you have to declare the array to be of size 11, not 10. The compiler will not do that for you.
I think you are somewhat confused about initializing an array of char in C++. char array[10] will have size 10, not size 11, however, char array[] = "1234567890"; will have size 11 because the initialization knows that your char array needs to end with a newline character.
Hey everyone, I am getting a heap corruption error I cannot figure out.
char * c = (char *) malloc(1);
// main loop
_gcvt_s(c, 100, ball->get_X_Direction(), 10);
if(pushFont(c, (SCREEN_WIDTH - 30), (SCREEN_HEIGHT - 40), message, screen,
font, textColor) == false)
{
//return 1; // error rendering text.
}
// end main loop
free(c);
The above code is the only time I use c pointer, in _gcvt_s and pushFont() which simply accepts a char * as its first parameter, and puts the text on the screen. Other then that I do not use c. When I try to free c after the main loop (which I think I am supposed to do), I get an error saying Visual Studio has acquired an error with the heap (heap corruption).
Commenting out the call to pushFont I still receive the error.
Can anyone explain to me why freeing a character (the 1 byte I allocated on the heap) would give me a heap corruption?
Lastly my main loop does a lot of stuff, a buddy and I are making a pong game with WinSocket, the rest of the main body is the loop for the game. I didnt think it was necessary to post, but I will update my post with the entire main loop if it is necessary, but I believe I am just off with my understanding of malloc() and free().
Thanks all,
Doesn't _gcvt_s use the 2nd parameter as the max size of the allocated buffer? You allocate 1 byte but tell _gcvt_s there are 100. So it happily writes up to 100 bytes into the buffer corrupting your heap. Then the free crashes. Allocate 100 bytes if you are going to potentially access 100 bytes.
EDIT: It sounds like you need to learn how C stores and manipulates strings. C stores strings as individual bytes in contiguous runs of memory followed by an extra character to indicate the end of the string. This extra character has an ASCII value of 0 (not the character '0' which is ASCII 48). So if you have a string like "HELLO", it takes 6 bytes to store - one for each of the 5 letters and the terminator.
In order for _gcvt_s() to return the value to your buffer, you need to include enough bytes for the conversion and the extra terminating byte. In the case of _gcvt_s(), you are asking for 10 characters of precision. But you also have to reserve room for the decimal point, the potential negative sign.
According to this [documentation](http://msdn.microsoft.com/en-us/library/a2a85fh5(VS.80).aspx), there is a #define in the headers for the maximum necessary size of the buffer: _CVTBUFSIZE. The example there should help you with this issue.
According to the documentation I can find _gcvt_s() takes a buffer and the length of that buffer as the first two arguments.
errno_t _gcvt_s(
char *buffer,
size_t sizeInBytes,
double value,
int digits
);
Your malloc()ed buffer is 1 byte long, you tell _gcvt_s() it is 100 bytes long. I would start looking here.
Why do you need to use the heap? If all you need is space for 1 char can't you just use a local variable:
char c;
_gcvt_s(&c...
?
You need more than one byte to store a float. Allocate a more practical length than 1 byte...
You also really don't need the heap, try a (slightly oversized) 16-byte buffer and giving _gcvt_s the correct buffer length (instead of the magical 100 you are giving it). De-magic your constants whilst you are at it.
const unsigned int cuFloatStringLength = 16;
const unsigned int cuFloatStringPrecision = 10;
char c[cuFloatStringLength];
_gcvt_s( c, cuFloatStringLength, ball->get_X_Direction(), cuFloatStringPrecision );
The problem should then be gone.