C++ Indexing TCHAR string - c++

I am doing some static analysis work on some old C++ code and my C++ is not the strongest. I have this piece of code:
void NIDP_clDPLogger::log(TCHAR *logString)
{
TCHAR temp_logString[1024] = {0};
_tcsncpy(temp_logString,logString,1024);
temp_logString[1023] = NULL;
...
The static analysis tool is complaining here of indexing logString (the parameter passed in to function) at 1024 when it may be shorter (the size varies, 1024 is the max. size I guess). So I guess my fix is to check the size of logString and use that, like this:
void NIDP_clDPLogger::log(TCHAR *logString)
{
size_t tempSize = sizeof(logString);
TCHAR temp_logString[tempSize] = {0};
_tcsncpy(temp_logString,logString,tempSize);
temp_logString[tempSize-1] = NULL;
I am just wondering, will this work OK? Can anybody see any flaws/problems? Building and testing this project is slightly difficult so I am basically just looking for a sanity check before I go through all that. Or is there a better way for me to do it? Can I pass a size_t value in to _tcsncpy, because a hardcoded int was there before?
Thanks for all help.

sizeof(logString) will return the size of a TCHAR*, not the size of the array passed as arrays decay to pointers when passed as argument.
If it is guaranteed that logString is null terminated you could obtain its length using _tcslen(). Otherwise, the only way to know the size of logString is to pass it into the function as another argument.

Related

Multidimensional array calculating

I've got an array of arrays of TCHAR, where I store file extension.
TCHAR *extens[] = { L".*", L".txt", L".bat" };
In order to go through it, I'm calculating it's length.
int extCount = sizeof(extens) / sizeof(TCHAR);
But for some reason the extCount's value is 2. I think the problem is because this is wrong calculation method, but then, how to count the number of elements ("words") in this array correctly?
UPD: I'am passing this array to function:
void func(TCHAR *path, TCHAR **names, TCHAR **extensions);
When i'am calculating this array lenght outside function it show correct number, but inside it always workis wrong (returns 2 or 1).
UPD2:
I tried to redeclare array like this:
TCHAR *extens[] = { L".txt", L".bat", L".txt", NULL };
And now inside function i'am doing something like that:
TCHAR **p = extensions;
int extCount = 0;
while (*p != NULL)
{
extCount++;
*p++;
}
extCount = cnt;
wsprintf(temp, L"%d", cnt);
MessageBox(NULL, temp, temp, MB_OK);
It works, but looks like its not so effective, because of walking two arrays, isn't it?
TCHAR *extens[] is an array of pointers of type TCHAR. And the size of such an array will be array_length * sizeof(pointer)).
Note: sizeof(pointer) on a system will be same for all datatypes.
You have an array of TCHAR*.
To get the length of the following array:
TCHAR *extens[] = { L".*", L".txt", L".bat" };
You need to use:
sizeof(extens) / sizeof(TCHAR*)
First of all, you have an array of pointers so you need
extCount = sizeof(extens) / sizeof(TCHAR*);
to calculate its size. However, this assumes that extens is still of an array-type. Once you pass it to a function expecting a TCHAR**, the array will decay to a pointer and its size information will be lost.
I think your best option would be to rewrite this in terms of std::string and std::vector. This is C++ so you might as well use its facilities. If this is not possible for any reason, and the arrays are known at compile time, you could templatize the function on array-sizes:
template <size_t N, size_t M>
void func(TCHAR *path, TCHAR *(&names)[N], TCHAR *(&extensions)[M]);
The syntax is a bit messy maybe. For example, TCHAR *(&names)[N] is read as: "names is a reference to an array of N pointers to TCHAR". Here, the size N is deduced by the compiler as long as you don't let the array decay to a plain pointer.

C++ Need explaination on `static const WCHAR*`

Making a Direct2D program, I want to convert from int to WCHAR so I wrote the following code
void DemoApp::OnRender() {
//...
int a = 256;
std::wstring wStr = std::to_wstring(a);
static const WCHAR* pStrNum = wStr.c_str();
//Print the number to the screen
_pRenderTarget->DrawText(
pStrNum,
sizeof(pStrNum)/sizeof(pStrNum[0]),
_pTextFormat,
rect,
_pBrush);
//...
};
However, after one loop, the pStrNum changed to something weird, with the starting character is 5028 decimal base.
After messing a bit, I changed the conversion code to
const WCHAR* pStrNum = wStr.c_str();
The string printed almost correctly on the screen and everything seems to be normal except for the sizeof(pStrNum)/sizeof(pStrNum[0]) having the value of 2, therefore print only the first two characters on the screen.After all, I have to use lstrlenW() to get the number of elements in that string.
I need explaination on why static const WCHAR* is different from const WCHAR* and causes error
And why sizeof() doesn't work in this case?
I think (and I'll know for sure If I get lots of downvotes) that the behaviour of your code is undefined
This is because
static const WCHAR* pStrNum = wStr.c_str();
has static storage will be initialised once.
But wStr will be initialised every time the function is called, and that is the problem: in all subsequent calls to the function, the pointer will be dangling and the behaviour is undefined.
If I were you, I'd evaluate the .c_str() on a just in time basis. There will be no performance overhead in doing this.
To answer your question: use wStr.size() to get the length of the string: sizeof() returns the size of the data type (evaluated at compile time), not the string length.
sizeof(pStrNum) gives you the size of WCHAR*, not the string it points to.
You can only calculate an array's length using sizeof(arr)/sizeof(arr[0]) when you have access to the array declaration. At other times, you need to pass a size along with the array or iterate over its elements until you find a sentinel element marking the end of the elements. For a C-style string, you can iterate over its elements until you find one with value \0. wcslen does this for wchar_t.
_pRenderTarget->DrawText(
pStrNum,
wcslen(pStrNum),
_pTextFormat,
rect,
_pBrush);
Or, simpler, as Kerrek SB suggests, remove all use of pStrNum
_pRenderTarget->DrawText(
wStr.data(),
wStr.size(),
_pTextFormat,
rect,
_pBrush);
sizeof gives you the size of the object representation of whatever you pass it. You are giving pStrNum to sizeof, and pStrNum is a const WCHAR*, so what you're getting is the size of the pointer. sizeof doesn't work out the length of strings.
The reason your code doesn't work is that the compiler uses the static type of the variable to evaluate sizeof. sizeof(pStrNum) will be either 4 or 8 bytes, depending on your OS, as the variable is a pointer.
Just rewrite the code as:
_pRenderTarget->DrawText(
wStr.c_str(),
wStr.length(),
_pTextFormat,
rect,
_pBrush);
and you'll be ok

Why does windows need the size when calling a function?

I am trying to learn a little c++ and I have a silly question. Consider this code:
TCHAR tempPath[255];
GetTempPath(255, tempPath);
Why does windows need the size of the var tempPath? I see that the GetTempPath is declared something like:
GetTempPath(dword size, buf LPTSTR);
How can windows change the buf value without the & operator? Should not the function be like that?
GetTempPath(buf &LPTSTR);
Can somebody provide a simple GetTempPath implementation sample so I can see how size is used?
EDIT:
Thanks for all your answers, they are all correct and I gave you all +1. But what I meant by "Can somebody provide a simple GetTempPath implementation) is that i have tried to code a function similar to the one windows uses, as follow:
void MyGetTempPath(int size, char* buf)
{
buf = "C:\\test\\";
}
int main(int argc, char *argv[])
{
char* tempPath = new TCHAR[255];
GetTempPathA(255, tempPath);
MessageBoxA(0, tempPath, "test", MB_OK);
return EXIT_SUCCESS;
}
But it does not work. MessageBox displays a "##$' string. How should MyGetTempPath be coded to work properly?
Windows needs the size as a safety precaution. It could crash the application if it copies characters past the end of the buffer. When you supply the length, it can prevent that.
Array variables work like pointers. They point to the data in the array. So there is no need for the & operator.
Not sure what kind of example you are looking for. Like I said, it just needs to verify it doesn't write more characters than there's room for.
An array cannot be passed into functions by-value. Instead, it's converted to a pointer to the first element, and that's passed to the function. Having a (non-const) pointer to data allows modification:
void foo(int* i)
{
if (i) (don't dereference null)
*i = 5; // dereference pointer, modify int
}
Likewise, the function now has a pointer to a TCHAR it can write to. It takes the size, then, so it knows exactly how many TCHAR's exist after that initial one. Otherwise it wouldn't know how large the array is.
GetTempPath() outputs into your "tempPath" character array. If you don't tell it how much space there is allocated in the array (255), it has no way of knowing whether or not it will have enough room to write the path string into tempPath.
Character arrays in C/C++ are pretty much just pointers to locations in memory. They don't contain other information about themselves, like instances of C++ or Java classes might. The meat and potatoes of the Windows API was designed before C++ really had much inertia, I think, so you'll often have to use older C style techniques and built-in data types to work with it.
Following wrapper can be tried, if you want to avoid the size:
template<typename CHAR_TYPE, unsigned int SIZE>
void MyGetTempPath (CHAR_TYPE (&array)[SIZE]) // 'return' value can be your choice
{
GetTempPath(SIZE, array);
}
Now you can use like below:
TCHAR tempPath[255];
MyGetTempPath(tempPath); // No need to pass size, it will count automatically
In your other question, why we do NOT use following:
GetTempPath(buf &LPTSTR);
is because, & is used when you want to pass a data type by reference (not address). I am not aware what buf is typecasted to but it should be some pointer type.
Can somebody provide a simple
GetTempPath implementation sample so I
can see how size is used?
First way (based on MAX_PATH constant):
TCHAR szPath[MAX_PATH];
GetTempPath(MAX_PATH, szPath);
Second way (based on GetTempPath description):
DWORD size;
LPTSTR lpszPath;
size = GetTempPath(0, NULL);
lpszPath = new TCHAR[size];
GetTempPath(size, lpszPath);
/* some code here */
delete[] lpszPath;
How can windows change the buf value without the & operator?
& operator is not needed because array name is the pointer to first array element (or to all array). Try next code to demonstrate this:
TCHAR sz[1];
if ((void*)sz == (void*)&sz) _tprintf(TEXT("sz equals to &sz \n"));
if ((void*)sz == (void*)&(sz[0])) _tprintf(TEXT("sz equals to &(sz[0]) \n"));
As requested, a very simple implementation.
bool MyGetTempPath(size_t size, char* buf)
{
const char* path = "C:\\test\\";
size_t len = strlen(path);
if(buf == NULL)
return false;
if(size < len + 1)
return false;
strncpy(buf, path, size);
return true;
}
An example call to the new function:
char buffer[256];
bool success = MyGetTempPath(256, buffer);
from http://msdn.microsoft.com/en-us/library/aa364992(v=vs.85).aspx
DWORD WINAPI GetTempPath(
__in DWORD nBufferLength,
__out LPTSTR lpBuffer
);
so GetTempPath is defined something like
GetTempPath(DWORD nBufferLength, LPTSTR& lpBuffer);
What mean, that compiler passes the value lpBuffer by referenece.

how to initialize a char array?

char * msg = new char[65546];
want to initialize to 0 for all of them. what is the best way to do this in C++?
char * msg = new char[65546]();
It's known as value-initialisation, and was introduced in C++03. If you happen to find yourself trapped in a previous decade, then you'll need to use std::fill() (or memset() if you want to pretend it's C).
Note that this won't work for any value other than zero. I think C++0x will offer a way to do that, but I'm a bit behind the times so I can't comment on that.
UPDATE: it seems my ruminations on the past and future of the language aren't entirely accurate; see the comments for corrections.
The "most C++" way to do this would be to use std::fill.
std::fill(msg, msg + 65546, 0);
Absent a really good reason to do otherwise, I'd probably use:
std::vector<char> msg(65546, '\0');
what is the best way to do this in
C++?
Because you asked it this way:
std::string msg(65546, 0); // all characters will be set to 0
Or:
std::vector<char> msg(65546); // all characters will be initialized to 0
If you are working with C functions which accept char* or const char*, then you can do:
some_c_function(&msg[0]);
You can also use the c_str() method on std::string if it accepts const char* or data().
The benefit of this approach is that you can do everything you want to do with a dynamically allocating char buffer but more safely, flexibly, and sometimes even more efficiently (avoiding the need to recompute string length linearly, e.g.). Best of all, you don't have to free the memory allocated manually, as the destructor will do this for you.
This method uses the 'C' memset function, and is very fast (avoids a char-by-char loop).
const uint size = 65546;
char* msg = new char[size];
memset(reinterpret_cast<void*>(msg), 0, size);
memset(msg, 0, 65546)
You can use a for loop. but don't forget the last char must be a null character !
char * msg = new char[65546];
for(int i=0;i<65545;i++)
{
msg[i]='0';
}
msg[65545]='\0';
The C-like method may not be as attractive as the other solutions to this question, but added here for completeness:
You can initialise with NULLs like this:
char msg[65536] = {0};
Or to use zeros consider the following:
char msg[65536] = {'0' another 65535 of these separated by comma};
But do not try it as not possible, so use memset!
In the second case, add the following after the memset if you want to use msg as a string.
msg[65536 - 1] = '\0'
Answers to this question also provide further insight.
If you panic and can not assign dynamic data to a const char* in a constructor you can insert each element of a dynamic buffer piece by piece. You can even snprintf() to the buffer before making the imprint.
client_id = new char[26] {
buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],
buf[10],buf[11],buf[12],buf[13],buf[14],buf[15],buf[16],buf[17],buf[18],buf[19],
buf[20],buf[21],buf[22],buf[23],buf[24],'\0'
};
To cover up what you have been doing, maybe the editor has an option where you can set the forecolor same as the background?
Before being fired you can actually prime the const char in the header file declaration with enough space and then later assign real data in the constructor. Great!
const char* client_id = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
It is a const pointer and does not have to be initialized before the constructor deals with it.
const char* client_id;
NOTE:
You can write at the top of the page: using namespace std,
and thus avoid writing std:: at the beginning of each command.
char * msg = new char[65546]={0};
This command reset all the array to 0.

Passing an array as a function parameter in C++

In C++, arrays cannot be passed simply as parameters. Meaning if I create a function like so:
void doSomething(char charArray[])
{
// if I want the array size
int size = sizeof(charArray);
// NO GOOD, will always get 4 (as in 4 bytes in the pointer)
}
I have no way of knowing how big the array is, since I have only a pointer to the array.
Which way do I have, without changing the method signature, to get the size of the array and iterate over it's data?
EDIT: just an addition regarding the solution. If the char array, specifically, was initialized like so:
char charArray[] = "i am a string";
then the \0 is already appended to the end of the array. In this case the answer (marked as accepted) works out of the box, so to speak.
Use templates. This technically doesn't fit your criteria, because it changes the signature, but calling code does not need to be modified.
void doSomething(char charArray[], size_t size)
{
// do stuff here
}
template<size_t N>
inline void doSomething(char (&charArray)[N])
{
doSomething(charArray, N);
}
This technique is used by Microsoft's Secure CRT functions and by STLSoft's array_proxy class template.
Without changing the signature? Append a sentinel element. For char arrays specifically, it could be the null-terminating '\0' which is used for standard C strings.
void doSomething(char charArray[])
{
char* p = charArray;
for (; *p != '\0'; ++p)
{
// if '\0' happens to be valid data for your app,
// then you can (maybe) use some other value as
// sentinel
}
int arraySize = p - charArray;
// now we know the array size, so we can do some thing
}
Of course, then your array itself cannot contain the sentinel element as content.
For other kinds of (i.e., non-char) arrays, it could be any value which is not legal data. If no such value exists, then this method does not work.
Moreover, this requires co-operation on the caller side. You really have to make sure that the caller reserves an array of arraySize + 1 elements, and always sets the sentinel element.
However, if you really cannot change the signature, your options are rather limited.
In general when working with C or low-level C++, you might consider retraining your brain to never consider writing array parameters to a function, because the C compiler will always treat them as pointers anyway. In essence, by typing those square brackets you are fooling yourself in thinking that a real array is being passed, complete with size information. In reality, in C you can only pass pointers. The function
void foo(char a[])
{
// Do something...
}
is, from the point of view of the C compiler, exactly equivalent to:
void foo(char * a)
{
// Do something
}
and obviously that nekkid char pointer contains no length information.
If you're stuck in a corner and can't change the function signature, consider using a length prefix as suggested above. A non-portable but compatible hack is to specify the array length in an size_t field located before the array, something like this:
void foo(char * a)
{
int cplusplus_len = reinterpret_cast<std::size_t *>(a)[-1];
int c_len = ((size_t *)a)[-1];
}
Obviously your caller needs to create the arrays in the appropriate way before passing them to foo.
Needless to say this is a horrible hack, but this trick can get out of trouble in a pinch.
It actually used to be a quite common solution to pass the length in the first element of the array. This kind of structure is often called BSTR (for “BASIC string”), even though this also denoted different (but similar) types.
The advantage over the accepted solution is that determining the length using a sentinel is slow for large strings. The disadvantage is obviously that this is a rather low-level hack that respects neither types nor structure.
In the form given below it also only works for strings of length <= 255. However, this can easily be expanded by storing the length in more than one byte.
void doSomething(char* charArray)
{
// Cast unnecessary but I prefer explicit type conversions.
std::size_t length = static_cast<std::size_t>(static_cast<unsigned char>(charArray[0]));
// … do something.
}
if it's nullterminated, strlen() would work.
You can't determine the size from charArray alone. That information is not automatically passed to the function.
Of course if it's a null-terminated string you can use strlen(), but you have probably considered that already!
Consider passing a std::vector<char> & parameter, or a pair of pointers, or a pointer plus a size parameter.
This is actually more C than C++, in C++ you'd probably rather use a std::vector. However, in C there's no way to know the size of an array. The compile will allow you to do a sizeof if the array was declared in the current scope, and only if it was explicitly declared with a size (EDIT: and "with a size", I mean that it was either declared with an integer size or initialized at declaration, as opposed to being passed as a parameter, thanks for the downvote).
The common solution in C is to pass a second parameter describing the number of elements in the array.
EDIT:
Sorry, missed the part about not wanting to change the method signature. Then there's no solution except as described by others as well, if there's some data that is not allowed within the array, it can be used as a terminator (0 in C-strings, -1 is also fairly common, but it depends on your actual data-type, assuming the char array is hypothetical)
In order for a function to know the number of items in an array that has been passed to it, you must do one of two things:
Pass in a size parameter
Put the size information in the array somehow.
You can do the latter in a few ways:
Terminate it with a NULL or some
other sentinel that won't occur in
normal data.
store the item count in the first entry if the array holds numbers
store a pointer to the last entry if the array contains pointers
try using strlen(charArray);
using the cstring header file. this will produce the number of characters including spaces till it reaches the closing ".
You are guarranteed to receive 4 in a 32-bit PC and that's the correct answer. because of the reason explained here and here.
The short answer is, you are actually testing the sizeof a pointer rather than an array, because "the array is implicitly converted, or decays, into a pointer. The pointer, alas, doesn't store the array's dimension; it doesn't even tell you that the variable in question is an array."
Now that you are using C++, boost::array is a better choice than raw arrays. Because it's an object, you won't loose the dimention info now.
I think you can do this:
size_t size = sizeof(array)/sizeof(array[0]);
PS: I think that the title of this topic isn't correct, too.
Dude you can have a global variable to store the size of the array which will be accessible throughout the program. At least you can pass the size of the array from the main() function to the global variable and you will not even have to change the method signature as the size will be available globally.
Please see example:
#include<...>
using namespace std;
int size; //global variable
//your code
void doSomething(char charArray[])
{
//size available
}