By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,405 Members | 1,102 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,405 IT Pros & Developers. It's quick & easy.

Problem with pointer to array of structures

P: n/a
I am trying to pass a pointer to an array of structures to function,
but
I have some problems. I am using MS Visual C++ 6.0, but I think
this is more of a C-problem than Windows programming specific. Here
is the relevant part of my code.

typedef struct
{
int iControlID;
char controlTxt[64];
} CONTROL_TXT;

void SetControlTxts(HWND hDlg, CONTROL_TXT *ctrlTxt[]);

void MyFunc(void)
{
static CONTROL_TXT ctrlTxts[] =
{
{ 1, "text 1" },
{ 2, "text 2" },
{ 3, "text 3" },
{ 0, "" } // marks end of table
};

<clip>

SetControlTxts(hDlg, &ctrlTxts[0]);
}
void SetControlTxts(HWND hDlg, CONTROL_TXT *ctrlTxt[])
{
int i, id;
char txt[64];

for (i = 0; &ctrlTxt[i]->iControlID != 0; i++)
{
id = &ctrlTxt[i]->iControlID;
strcpy(txt, &ctrlTxt[i]->controlTxt);
//strcpy(txt, (char*)ctrlTxt[i]->controlTxt);
//SetDlgItemText(hDlg, ctrlTxt[i]->iControlID,
ctrlTxt[i]->controlTxt);
SetDlgItemText(hDlg, id, txt);
}

return;

}

I get some compiler warnings. Function call "SetControlTxts(hDlg,
&ctrlTxts[0]);
":
warning C4047: 'function' : 'struct CONTROL_TXT ** ' differs in levels
of indirection from 'struct CONTROL_TXT *'
warning C4024: 'SetControlTxts' : different types for formal and
actual parameter 2

"id = &ctrlTxt[i]->iControlID;":
warning C4047: '=' : 'int ' differs in levels of indirection from 'int
*'

"strcpy(txt, &ctrlTxt[i]->controlTxt);":
warning C4047: 'function' : 'const char *' differs in levels of
indirection from 'char (*)[64]'
warning C4024: 'strcpy' : different types for formal and actual
parameter 2

Strcpy also causes access violation in Visual C++. However, I can get
valid value of "id", the debugger shows it correctly.

I also tried casting to char*:
strcpy(txt, (char*)&ctrlTxt[i]->controlTxt);
but it also causes access violation.

Any info what am I doing wrong here?

Timo
Nov 14 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
nrk
Timo wrote:
I am trying to pass a pointer to an array of structures to function,
but
I have some problems. I am using MS Visual C++ 6.0, but I think
this is more of a C-problem than Windows programming specific. Here
is the relevant part of my code.

typedef struct
{
int iControlID;
char controlTxt[64];
} CONTROL_TXT;

void SetControlTxts(HWND hDlg, CONTROL_TXT *ctrlTxt[]);
The second parameter here is a pointer-to-pointer-to CONTROL_TXT. IOW, this
prototype is equivalent to:
void SetControlTxts(HWND hDlg, CONTROL_TXT **ctrlTxt);

However, what you're passing is essentially a pointer-to CONTROL_TXT (Search
the group archives for Chris Torek's "The" rule to see why this is the
case). So what you really want is either one of:
void SetControlTxts(HWND hDlg, CONTROL_TXT *ctrlTxt);
or
void SetControlTxts(HWND hDlg, CONTROL_TXT ctrlTxt[]);

void MyFunc(void)
{
static CONTROL_TXT ctrlTxts[] =
{
{ 1, "text 1" },
{ 2, "text 2" },
{ 3, "text 3" },
{ 0, "" } // marks end of table
};

This declares ctrlTxts to be an array of CONTROL_TXT. When passed as a
parameter to a function, it decays into a pointer to the first element of
the array.
<clip>

SetControlTxts(hDlg, &ctrlTxts[0]);
This is unnecessary. You can simply write:
SetControlTxts(hDlg, ctrlTxts);
to get the same effect.
}
void SetControlTxts(HWND hDlg, CONTROL_TXT *ctrlTxt[])
Again, change this definition to match the prototype as shown above.
{
int i, id;
char txt[64];

for (i = 0; &ctrlTxt[i]->iControlID != 0; i++)
-> binds closer than &. So what you're doing is equivalent to:
&(ctrlTxt[i]->iControlID) != 0

Unfortunately, your choice of integer constant here is such that, the
compiler thinks this is fine, even though this is quite clearly not what
you want.

Why not:
for ( i = 0; ctrlTxt[i].iControlID != 0; i++ )
?
Similar fixes can be applied to other such mistakes.
{
id = &ctrlTxt[i]->iControlID; See above. However, here your compiler has a legitimate reason to complain.
The rhs is clearly an address and lhs is an int. Hence the noise.
strcpy(txt, &ctrlTxt[i]->controlTxt); See above.
//strcpy(txt, (char*)ctrlTxt[i]->controlTxt);
//SetDlgItemText(hDlg, ctrlTxt[i]->iControlID,
ctrlTxt[i]->controlTxt);
SetDlgItemText(hDlg, id, txt);
}

return;

}

I get some compiler warnings. Function call "SetControlTxts(hDlg,
&ctrlTxts[0]);
":
warning C4047: 'function' : 'struct CONTROL_TXT ** ' differs in levels
of indirection from 'struct CONTROL_TXT *'
warning C4024: 'SetControlTxts' : different types for formal and
actual parameter 2

"id = &ctrlTxt[i]->iControlID;":
warning C4047: '=' : 'int ' differs in levels of indirection from 'int
*'

"strcpy(txt, &ctrlTxt[i]->controlTxt);":
warning C4047: 'function' : 'const char *' differs in levels of
indirection from 'char (*)[64]'
warning C4024: 'strcpy' : different types for formal and actual
parameter 2

All fine and excellent warnings. It's good that you've set your compiler's
warning levels high enough to catch these mistakes.
Strcpy also causes access violation in Visual C++. However, I can get
valid value of "id", the debugger shows it correctly.

I also tried casting to char*:
strcpy(txt, (char*)&ctrlTxt[i]->controlTxt);
but it also causes access violation.

This tells you that you are not yet strong enough in the language to be
using dubious constructs such as casts. Never ever use a cast to silence
the compiler unless you're absolutely 200% certain that you know what
you're doing. Casts do *not* fix incorrect code, and often prevent you
from getting useful diagnostics from the compiler.

-nrk.
Any info what am I doing wrong here?

Timo


--
Remove devnull for email
Nov 14 '05 #2

P: n/a
Timo wrote:
a pointer to an array of structures CONTROL_TXT *ctrlTxt[]


That's an array of pointers to structures.

You want:
CONTROL_TXT *ctrlTxt

Make the call like this:
SetControlTxts(hDlg, ctrlTxts);

Access members like this:
ctrlTxt[i].iControlID

--
pete
Nov 14 '05 #3

P: n/a
pete wrote:
.... snip ...
Whenever you pass *any* array name as an argument, the name of
the array is converted to a pointer to it's first element.

I prefer
void func(int *array);
over
void func(int array[]);

Even though they mean exactly the same thing,
the true type of the parameter, is a pointer.


However func may then be called with a pointer to an array[1] of
int, or with a void*, or with the address of some individual int.
So it makes more sense to make the requisite parameter form
explicit. Thus I would use:

void func(int *i); /* pointer to an individual integer */
void func(int a[]); /* pointer to an actual array, but .. */
void func(int a[], size_t sz); /* an actual array, safer */

of course, arrays may have internal end markers, such as strings,
but such markers do not indicate maximum capacity.

The point of the above is that the user of func has an idea of its
requirements from the prototype alone.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.