I do not understand why the pointer addition is failing.
DWORD *pipebuf=new DWORD[10001];
Command *cr= (Command*)pipebuf;
cr->command=2;
DWORD* rooms=(pipebuf+1); //should work fine..sets the room pointer equal to pipe[2]
*rooms=buff3; //where buff3=100
Yet, the value of pipebuf only contains the value of command, it does not contain the value of buff3. Yet, when I remove the new keyword it works fine...Why?
DWORD=unsigned_int
Command is a class with a DWORD variable of command.. something like this
Class Command {
DWORD command;
}
The addition moves the pointer forward one, causing it to point at the second DWORD in your array. *(pipebuf+1) is precisely equivalent to pipebuf[1]; after your code runs, *pipebuf aka pipebuf[0] aka cr->command is equal to 2, while *(pipebuf+1) aka *rooms aka pipebuf[1] is equal to 100.
Note however that typecasting between pointer types in C++ is often considered bad style and can in many circumstances have undesirable results. If you are allocating an array of Command's, then use new Command[...]; if you want DWORD's, then don't cast into Command*.
Sometimes you have to cast pointers between types, but generally you should only do that if you know exactly what you're doing and why you can't avoid doing so.
Furthermore, if you do need to, you should either be using static_cast (in cases like this) or dynamic_cast (in cases where the types are related by inheritance; this usage is much safer generally).
class Command is a user defined type and DWORD is a primitive data type ( unsigned int ). In that case, why doing this -
Command *cr= (Command*)pipebuf;
class Command {
public : // Added public keyword
DWORD command; // DWORD is a typedef for unsigned int as you mentioned.
}; // class definition should end with a semi-colon
So, this is the way to do -
Command *cr = new Command[10001] ;
DWORD *pipebuf=new DWORD[10001];
// After assigining values to DWORD pointed locations. Then you can do this -
cr->command = pipebuf[0] ; // this sets the value of cr[0].command.
I'd make this a comment, but I can't do code formatting in those.
I ran this code, and the output is "2 100" as expected:
#include <iostream>
using namespace std;
typedef unsigned int DWORD;
class Command {
public:
DWORD command;
};
int main()
{
DWORD buff3 = 100;
DWORD *pipebuf = new DWORD[10001];
Command *cr = (Command*)pipebuf;
cr->command = 2;
DWORD *rooms = (pipebuf+1);
*rooms = buff3;
std::cout << pipebuf[0] << " " << pipebuf[1] << endl;
}
AFAICT that's the simplest way you could expand your question into a complete program.
Could you try taking this and adding more stuff from the original code until you get the problem to appear?
Related
I'm working with WinAPI's CreateDialogIndirect function, which has some requirements on the DLGTEMPLATE and DLGTEMPLATEEX structures pointed to by the second parameter. My code works well, however, I would like to get rid of the #define macros.
I created a simplified example to focus on the macros. This is a working program with macros, it can be compiled, and outputs what is expected:
#include <iostream>
int wmain()
{
#define TITLE L"Title"
struct {
wchar_t title[ sizeof( TITLE ) / sizeof( TITLE[ 0 ] ) ];
int font_size;
} s = {
TITLE,
12,
};
std::wcout
<< L"s.title = " << s.title << std::endl
<< L"s.font_size = " << s.font_size << std::endl;
return 0;
}
In Visual Studio 2022, I see three dots at the #define macro, and I can read the following tooltip:
Macro can be converted to constexpr
Show potential fixes
Convert macro to constexpr
I would like to see it converted to something to avoid macros, so I click on it, and the code is changed to this:
#include <iostream>
int wmain()
{
constexpr auto TITLE = L"Title";
struct {
wchar_t title[ sizeof( TITLE ) / sizeof( TITLE[ 0 ] ) ];
int font_size;
} s = {
TITLE,
12,
};
std::wcout
<< L"s.title = " << s.title << std::endl
<< L"s.font_size = " << s.font_size << std::endl;
return 0;
}
If I hit F7 to compile, I get the following error message:
example.cpp(10,9): error C2440: 'initializing': cannot convert from 'const wchar_t *const ' to 'wchar_t'
I would not like to enter L"Title" two times, and I would not like to calculate the length of the string manually. So, what can be a good substitute for the macro, which is capable of both initializing the struct and determining the size of the array in the struct?
A template is a reasonably common replacement for macro usage. Since you don't want to manually calculate the length of the string (I don't blame you), let's make a length (the array length, not the string length) the template parameter. Your anonymous struct becomes a likely candidate for being the templated entity, as you do end up with a different type each time you change the length of your title.
The actual conversion to a template is simple enough (given the level of the question) that I won't go over the details here. The nifty part comes when you write a constructor. By using the template parameter in the argument list, the compiler will be able to deduce it. This gives you the ease-of-use you appear to be looking for, albeit at the cost of some additional setup.
Caveat: Deducing the template parameter via an argument to the constructor is a C++17 feature. Anyone stuck on C++11 or 14 (hopefully not many of you) can get a similar result by writing a separate function template that constructs and returns a struct. I'll leave that as an exercise.
#include <iostream>
#include <cstring> // For memcpy
template <size_t N>
struct DlgTemplate {
wchar_t title[N];
int font_size;
// Constructor that will deduce `N`.
// For those not familiar with this syntax: the incoming title_ is a
// reference to an array with exactly N elements.
DlgTemplate(const wchar_t (&title_)[N], int font_size_) :
font_size(font_size_)
{
// Copy the title.
std::memcpy(title, title_, sizeof(title));
}
// Reminder: N is the array length, which includes the null terminator.
// The string length is N-1.
};
int main()
{
// As of C++17, the template argument can be deduced here.
auto s = DlgTemplate(L"Title", 12);
std::wcout
<< L"s.title = " << s.title << std::endl
<< L"s.font_size = " << s.font_size << std::endl;
}
The next consideration is probably how to deal with all the fields that were mercifully left out of the question. One option is to add more parameters to the constructor to handle all of the fields. However, in the interest of readability, I might be inclined to remove font_size_ as a constructor parameter (remembering to mark the constructor explicit) then set each field after construction. The following is what I have in mind for the initialization.
auto s = DlgTemplate(L"Title");
s.font_size = 12;
//s.other_field = value;
// etc.
There is one important detail to note from the question. The "potential fix" implemented by Visual Studio caused the length information to be lost.
constexpr auto TITLE = L"Title";
defines TITLE to be a pointer (to const wchar_t). Its size is fixed, independent of the length of the title. The calculation sizeof( TITLE ) / sizeof( TITLE[ 0 ] ) does not give the length of the title, and this TITLE will not work with the template.
constexpr wchar_t TITLE[] = L"Title";
defines TITLE to be an array, with the length information kept as part of the type. This TITLE can be used with the template.
Depends what you really want. One way is to use std::wstring_view instead of the array, but this may suit your needs or not.
If it does, it's pretty easy:
struct {
std::wstring_view title = L"Title";
int font_size{12};
} s;
DLGTEMPLATEEX is a special case. In fact, there is no structures with such a name in the wndows headers. If you want to use a structure, you must create you own, with custom array sizes.4
Example
constexpr TCHAR TITLE[] = _T("Title"); // IMPORTANT! To be 100% sure that's a array,
// declare it explicitely.
struct MyDlgTemplateEx {
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
TCHAR menu[1];
TCHAR WwindowClass[1];
TCHAR title[sizeof(TITLE) / sizeof(TITLE[0]);
WORD pointsize;
WORD weight;
BYTE italic;
BYTE charset;
TCHAR typeface[1]; // a NULL string.
};
The first thing that's obvious it that there are quite a few member variables. Doing unnamed in-place initialization (as in your example), with no explicit member names can very easily lead to mistakes and bugs.
The most common way of initializing such large structures is explicitely:
// ...
MyDlgTemplateEx tmpl = {}; // this declatres and fills structure with zeroes.
// initialize all non-zero members explicitely.
// cutting and pasting the structure declaration and editing around that is fairly fast.
tmpl.dlgVer = 1;
tmpl.signature = 0xFFFF; // this is a DLGTEMPLATEEX struct.
tmpl.exStyle = WS_EX_DLGMODALFRAME;
tmpl.style = WS_CAPTION;
tmpl.cDlgItems = 1;
tmpl.x = 10;
tmpl.y = 10;
tmpl.cx = 100;
tmpl.cy = 100;
_tcscpy_s(tmpl.title, TITLE); // must copy into array that's in structure.
Given these typedefs and the value below:
typedef void GTVOID;
typedef GTVOID *PARAM_VALUE;
typedef unsigned long UDGT32
typedef UDGT32 PARAM_CONST;
typedef signed long DGT32;
typedef DGT32 RESULT_FUNC;
DWORD value = 1; // given from a define
How I can convert it to satisfy the needs of that device SDK function in C++?
RESULT_FUN RSetParam( PARAM_CONST DeviceParameter, PARAM_VALUE value);
The C reference code in samples is:
RSetParam( R_SOME_PARAM_CONST, (PARAM_VALUE)value );
I tried it below, but it's just weird. It compiles ok, works all day long and by some
creepy luck, starts throwing access violations out of blue:
RSetParam(R_SOME_PARAM_CONST, reinterpret_cast<void*> (value));
What I'm doing wrong?
You have tried to reinterpret the value 1 as an address. Depending on what the function RSetParam is doing with this address (value), the program may seg-fault. Especially, if it tries to write to this address.
I think, the function RSetParam awaits an address to a variable as second argument. The type of the variable might depend on something else, that is, why the adress must be passed as void *.
So, if you want to pass number 1 as DWORD you have to allocate a variable on the stack first and then pass its address:
DWORD tmp = 1; // given from define
RSetParam( R_SOME_PARAM_CONST, (PARAM_VALUE) &tmp ); // note the '&' !
I am working on a test which checks if all class attributes are initialized in a constructor.
My current solution works for non pointer attributes:
void CSplitVectorTest::TestConstructorInitialization()
{
const size_t memorySize = sizeof(CSplitVector);
char* pBuffer1 = (char*) malloc(memorySize);
char* pBuffer2 = (char*) malloc(memorySize);
memset(pBuffer1,'?',memorySize);
memset(pBuffer2,'-',memorySize);
new(pBuffer1) CSplitVector;
new(pBuffer2) CSplitVector;
const bool bObjectsAreEqual = memcmp(pBuffer1,pBuffer2,memorySize)==0;
if (!TEST(bObjectsAreEqual))
{
COMMENT("Constructor initialization list not complete!");
}
free(pBuffer1);
free(pBuffer2);
}
Do you have an idea how could it be improved to test if pointers are initialized?
Your test checks whether every byte of the object has been written over by the constructor. As a straight memory check it looks OK, although if the class contains other objects which don't necessarily initialise themselves fully, you may be in trouble.
That said, my main question would be: Is it really an effective test? For example, is it critical that every attribute in the CSplitVector class is initialised by the initialisation list? Do you perhaps have some which may not need to be initialised at this point? Also, how about checking whether the attributes are set to values that you'd expect?
Instead of comparing byte by byte, you probably should use the right padding or word size, and test if any byte of each word got initialized. That way you will probably get around compiler using padding and constructor leaving uninitialized bytes between padded shorter-than-word fields.
To test the real padding size, shooting from the hip, following code should do it pretty reliably:
struct PaddingTest {
volatile char c; // volatile probably not needed, but will not hurt either
volatile int i;
static int getCharPadding() {
PaddingTest *t = new PaddingTest;
int diff = (int)(&(t->i)) - (int)&((t->c));
delete t;
return diff;
}
}
Edit: You still need the two objects, but you no longer compare them to each others, you just compare each initialized data to the memset value, and if either object has any change, it means the word got touched (also on the other one, it's just chance that it got initialized to same value you memset).
I found a solution for mentioned problems, tested it with initialized/not initialized pointers and with different length types.
In test header I added #pragma pack(1) (I am working on gcc)
#pragma pack(1)
#include <CSplitVector>
Test got a little bit complicated:
void CSplitVectorTest::TestConstructorInitialization()
{
const size_t memorySize = sizeof(CSplitVector);
char* pBuffer = (char*) malloc(memorySize);
memset(pBuffer,'?',memorySize);
CSplitVector* pSplitVector = new(pBuffer) CSplitVector;
// find pointers for all '?'
QList<char*> aFound;
char* pFoundChar = (char*) memchr(pBuffer,'?',memorySize);
while (pFoundChar)
{
aFound.append(pFoundChar);
char* pStartFrom = pFoundChar+1;
pFoundChar = (char*) memchr(pStartFrom,'?',memorySize-(int)(pStartFrom-pBuffer));
}
// if there are any '?'....
if (aFound.count())
{
// allocate the same area with '-'...
pSplitVector->~CSplitVector();
memset(pBuffer,'-',memorySize);
pSplitVector = new(pBuffer) CSplitVector;
// and check if places found before contain '-'
while (aFound.count())
{
pFoundChar = aFound.takeFirst();
if (*pFoundChar=='-')
{
// if yes then class has uninitialized attribute
TEST_FAILED("Constructor initialization list not complete!");
pSplitVector->~CSplitVector();
free(pBuffer);
return;
}
}
}
// if no then all attributes are initialized
pSplitVector->~CSplitVector();
free(pBuffer);
TEST(true);
}
Feel free to point any flaws in this solution.
Currently learning c++ and nowhere else better to ask something than to the experts of S.O. I Couldn't find more complete and better answers than here. So there it goes.
DWORD dw = 5;
cout << &dw;
Displays the address where the value of dw is stored.
But then why:
void Display( DWORD &dwUserId )
{
cout << dwUserId;
}
int _tmain( int argc, _TCHAR* argv[] )
{
DWORD dw = 5;
Display( dw );
}
Why on this example it is displayed the value of dw and not dw address?
& has two different meanings in this context:
placed in a declaration, it means the variable is a reference. In your case, you pass the parameter by reference.
outside a declaration, before a variable, it takes its address.
Besides these, it can also mean the bitwise AND operator
int x;
int& y = x; //y is a reference to x
int* z = &x; //& takes the address of x and assigns it to z
y & x; //bitwise AND
DWORD &dwUserId as a parameter to a function is a reference to DWORD.
In C++, the & operator does two things, depending on context:
When used in an r-value expression, it returns the address-of a value. e.g. void* ptr = &myObject;
When used in a type specifier it modifies the type to be a "reference-of" type. This is similar to how references work in Java and .NET. e.g. int& ref = myInt;
In your case, your dwUserId parameter is actually of type "reference to DWORD".
If you want to change it to get the address then do this:
void Display(DWORD* userId) {
cout << userId;
}
Display( &dw );
Also, please void TCHAR types. MBCS is deprecated. Win32 Unicode and wchar_t is the future :) Also avoid Hungarian notation. This isn't the 1980s. We have IDEs now.
Because when you use the & sign before a parameter name on a function definition you are telling the compiler to pass that parameter as a reference, i.e., don't make a copy of it.
When you use it before a variable name somewhere in the code you are telling the compiler to use the variable address instead of his value.
I am trying to use a function provided in 3rd party documentation and am having trouble getting my head around it. I recently figured out the meaning of IN/OUT variables and how to work with them. The problem with this function is it has several different types all combined. I am really confused how to access these array elements. Provided below is a screenshot of the function information.
This is the code I am working with:
BYTE numDevices = 10;
BYTE devices;
ULONG devicesArray = QCWWAN2kEnumerateDevices(&numDevices,&devices);
//How do I access the elements in the returned array?
ULONG IS THE RETURN CODE TO SEE IF IT FAILED/WHY
You need to get a debugger on it. It is unclear whether the QCWWAN2kEnumerateDevices allocates memory for your devices. If it doesn't (I doubt it does, knowing Win32API) your
BYTE devices;
should instead be
struct DEVICE_ARRAY_ELEM {
char devID[256];
char devKey[16];
};
DEVICE_ARRAY_ELEM *pDevices = malloc(sizeof(DEVICE_ARRAY_ELEM) * 10);
ULONG devicesArray = QCWWAN2kEnumerateDevices(&numDevices, (pDevices);
//Do stuff
free((void *)pDevices);
EDIT___ sorry that was C, here it is in C++
struct DEVICE_ARRAY_ELEM {
char devID[256];
char devKey[16];
};
DEVICE_ARRAY_ELEM *pDevices = new DEVICE_ARRAY_ELEM[10];
ULONG devicesArray = QCWWAN2kEnumerateDevices(&numDevices, pDevices);
//do stuff
delete [] pDevices;
To access use:
pDevices[devnum].devID[IDIndex];
Improving upon John Silver's answer
// IN A HEADER:
typedef struct DEVICE_ARRAY_ELEM {
char devID[256];
char devKey[16];
} DEVICE_ARRAY_ELEM; // This defines a struct to hold the data brought back
// it also type defs 'struct DEVICE_ARRAY_ELEM' to 'DEVICE_ARRAY_ELEM' for convienence
// IN YOUR CODE:
// This pointer should be wrapped in a auto_ptr to help with RAII
DEVICE_ARRAY_ELEM *pDevices = new DEVICE_ARRAY_ELEM[10]; // allocate 10 elements in-line
ULONG errorCode = QCWWAN2kEnumerateDevices(&numDevices, (BYTE*)pDevices); // get them
// Here is the hard part: iterating over the array of devices returned
// as per the spec numDevices is now the number of devices parsed
for(int i = 0; i < numDevices; i++) {
printf("%s\n", pDevices[i].devID); // is the name of the device (a character array)
}
delete [] pDevices;
EDIT
I now use numDevices do iterate over the array since the spec says that is the number of devices enumerated after the function call
EDIT AGAIN
Here is the code working based on my assumptions: IDEONE
The code has some typedefs and a definition of what I think the QCWWAN2kEnumerateDevices operates. So those should be ignored, but the code is compiles and performs as expected