Discussion Forum

Standard Struct?

Next Thread | Thread List | Previous Thread Start a Thread | Settings

DetailsMessage
Read-Only
Author
Craig Rohe
Posted
29-Sep-2007 01:17 GMT
Toolset
C51
New! Standard Struct?

Having some problems working with a struct typedef. In RTX51, one of the system functions takes as an argument a pointer to a struct:

//function prototype
signed char os_check_mailboxes (t_rtx_allmbxtab xdata *table);
...
/* Type definition for system call os_check_mailboxes */
typedef struct {
            unsigned char message_cnt;
            unsigned char read_task_cnt;
            unsigned char write_task_cnt;
        } t_rtx_allmbxtab[8];

I've never seen an array-of-structs declared within the typedef before, and couldn't find any literature about it. It's declared like a single struct, and used just like an array of structs:

t_rtx_allmbxtab xdata mytable;

if(mytable[x].message.cnt < 2)...

however, I get a warning "C182: pointer to different objects" when trying to use it with the actual system function (exactly as shown in the RTX51 user manual):

os_check_mailboxes(&mytable); //<-- generates warning!

I'm not sure exactly how the array as part of the data type affects this, so i'm stumped. However, that didn't stop me from trying random things to see what DID work. Here's what I came up with; maybe somebody can explain to me why this works:

//declare as an array, effectively making a 2D array
//with one dimension being size 1 only
t_rtx_allmbxtab xdata mytable[1];

//use as a normal 2D array
if(mytable[0][x].message.cnt < 2)...

//system function now works fine. no warnings.
os_check_mailboxes(&mytable);

//using (&mytable[0]) or (&mytable[0][0]) instead will generate 'pointer to different objects' warnings.
Read-Only
Author
Dan Henry
Posted
29-Sep-2007 05:06 GMT
Toolset
C51
New! RE: Standard Struct?

All C51 mem-space'isms and RTX51'isms cast aside, a review of basic C could be beneficial.

t_rtx_allmbxtab xdata mytable;

if(mytable[x].message.cnt < 2)...

however, I get a warning "C182: pointer to different objects" when trying to use it with the actual system function (exactly as shown in the RTX51 user manual):

os_check_mailboxes(&mytable); //<-- generates warning!


mytable is an array, the name of which produces its (implicit) address. Specifying the address of an (implicit) address could reasonably generate a warning.

Read-Only
Author
Hans-Bernhard Broeker
Posted
29-Sep-2007 21:15 GMT
Toolset
C51
New! RE: Standard Struct?

Specifying the address of an (implicit) address could reasonably generate a warning.

No. Such a warning would be quite unreasonable. Taking the address of an array to pass it by reference is unusual, but by no means something to warn about. Just because arrays automagically decay into pointers to their first element when necessary doesn't mean they can't have their address taken and used like any other variable.

Read-Only
Author
Dan Henry
Posted
29-Sep-2007 21:30 GMT
Toolset
C51
New! RE: Standard Struct?

"Such a warning would be quite unreasonable."

An error would be unreasonable. A warning is allowed, is justified, is not unreasonable, but is not required.

Read-Only
Author
Dan Henry
Posted
29-Sep-2007 21:38 GMT
Toolset
C51
New! RE: Standard Struct?

I should add that I don't necessarily agree with the exact warning the OP claimed to get. Something closer to lint's warning (suspicious use of &) would be more appropriate.

Read-Only
Author
Hans-Bernhard Broeker
Posted
30-Sep-2007 12:57 GMT
Toolset
C51
New! RE: Standard Struct?

is justified,

Pray tell: by what?

Read-Only
Author
Dan Henry
Posted
30-Sep-2007 18:08 GMT
Toolset
C51
New! RE: Standard Struct?

"Pray tell: by what?"

An implementation can produce warnings about anything it wants. An implementation producing warnings in suspect situations (e.g., unreferenced variables, unreachable code, 'void' statements, etc.) can justifiably produce a warning about the unnecessary use of '&'.

Read-Only
Author
Hans-Bernhard Broeker
Posted
30-Sep-2007 18:31 GMT
Toolset
C51
New! RE: Standard Struct?

can justifiably produce a warning about the unnecessary use of '&'.

... except that the use of & is necessary in the case at hand. The code as posted(!) would be incorrect if that '&' was left out. It's correct and doesn't deserve any kind of warning, as-is.

Generally speaking, mytable and &mytable are both perfectly correct arguments to pass to a called function. Only one of them has the correct type, though. Which that is depends on whether the called function's argument type is "pointer to element", "array", or "pointer to array".

As per the declarations actually posted by the OP, &mytable is correct, and mytable is not. The warning is unreasonable for the posted code, so either the posted code is not what the OP actually compiled to get the warning, or the compiler is emitting an unjustifiable warning.

Read-Only
Author
Hans-Bernhard Broeker
Posted
30-Sep-2007 13:06 GMT
Toolset
C51
New! RE: Standard Struct?

mytable is an array, the name of which produces its (implicit) address.

Not in the programming language C it doesn't. The name of an array, just like with any other variable, specifies its value, i.e. a combination of type and address. It'll implicitly convert into into a pointer to the first element in most circumstances. Taking the address of the address is not one of those circumstances, so this:

Specifying the address of an (implicit) address could reasonably generate a warning.

doesn't even apply. &mytable is not taking the address of an address, it's taking the address of a variable. The type of the resulting term is "pointer to array[8] of struct {...}", and it's a perfectly allowed, correct operation. There's absolutely nothing to warn about.

Read-Only
Author
Hans-Bernhard Broeker
Posted
30-Sep-2007 14:01 GMT
Toolset
C51
New! RE: Standard Struct?

Taking the address of the address is not one of those circumstances,

Editing mishap. Make that

Taking the address of the array is not one of those circumstances,

Read-Only
Author
Dan Henry
Posted
30-Sep-2007 19:07 GMT
Toolset
C51
New! RE: Standard Struct?

"... a review of basic C could be beneficial."

For me.

Read-Only
Author
Hans-Bernhard Broeker
Posted
29-Sep-2007 21:01 GMT
Toolset
C51
New! RE: Standard Struct?

It's declared like a single struct,

No. It's defined as a variable. The type of that is what the typedef says it is --- in this case, it's an array of untagged structs.

I get a warning "C182: pointer to different objects" when trying to use it with the actual system function (exactly as shown in the RTX51 user manual):

The warning doesn't match the posted code, so I suspect you must have a mismatch between the actual code and the posted.

Read-Only
Author
Craig Rohe
Posted
1-Oct-2007 04:20 GMT
Toolset
C51
New! RE: Standard Struct?

The warning doesn't match the posted code, so I suspect you must have a mismatch between the actual code and the posted.

Relevant lines of code copied directly from my project that produce the "pointer to different objects" warning:

t_rtx_allmbxtab xdata mbxtable;
...
os_check_mailboxes(&mbxtable);
for(i=0; i<mbxtable[MBX_DEBUG].message_cnt; i++) {...
Read-Only
Author
Hans-Bernhard Broeker
Posted
2-Oct-2007 20:32 GMT
Toolset
C51
New! RE: Standard Struct?

Relevant lines of code copied directly from my project

Unfortunately you've left out a crucial one: the actual prototype definition of function os_check_mailboxes().

What's really needed is a minimal, self-contained example, i.e. a complete, compilable source code snippet without #include's that, compiled on its own, yields the warning.

Read-Only
Author
barry gordon
Posted
2-Oct-2007 20:03 GMT
Toolset
C51
New! RE: Standard Struct?

The way it should be coded is:

/* Define the structure */
typedef struct {
            unsigned char message_cnt;
            unsigned char read_task_cnt;
            unsigned char write_task_cnt;
        } rtx_allmbxtab_t;


/* Create a variable of type struct */
rtx_allmbxtab_t rtx_allmbxtab[8];

/* Now you can pass an address of a variable of type struct */
&rtx_allmbxtab

</prev>


Read-Only
Author
Hans-Bernhard Broeker
Posted
2-Oct-2007 20:26 GMT
Toolset
C51
New! RE: Standard Struct?
/* Create a variable of type struct */
rtx_allmbxtab_t rtx_allmbxtab[8];

/* Now you can pass an address of a variable of type struct */
&rtx_allmbxtab

You can, but not like that. &rtx_allmbxtab is the address of a variable of type array of something. It is not, repeat not, a pointer to a struct. If you want a pointer-to-struct, pass rtx_allmbxtab as it is, or, if you like to be extra verbose:

&(rtx_allmbxtab[0])
Read-Only
Author
barry gordon
Posted
2-Oct-2007 21:18 GMT
Toolset
C51
New! RE: Standard Struct?

I stand corrected. The name of an array is the address, unless you specified the index. But is not the address of a struct, it is the address of a variable of type struct.

Also in the code, do not use unsigned char. Use a typedef to make it portable, such as:

typedef unsigned char uint8_t;
typedef signed char    int8_t;

uint8_t myFu;
int8_t  myBar;

Read-Only
Author
Andy Neil
Posted
2-Oct-2007 21:55 GMT
Toolset
C51
New! Portable

To be portable, it would have to have a condition to select the right definition for the particular compiler; eg,

#if defined __C51__
typedef unsigned char uint8_t;
typedef signed char    int8_t;
#elif defined <other-compiler-flag>
// suitable typedefs
#else
#error Unsupported compiler
#endif
Read-Only
Author
barry gordon
Posted
2-Oct-2007 23:28 GMT
Toolset
C51
New! RE: Portable

You just need to change the typedefs for the various types. 8 bits is 8 bits and 16 bits is 16 bits no what compiler your using. Everything depends on the native registor size of the uProcessor. I have code written for an 8-bit processor running on an ARM in 32-bit mode.

Read-Only
Author
Andy Neil
Posted
3-Oct-2007 00:12 GMT
Toolset
C51
New! RE: Portable

"You just need to change the typedefs for the various types."

Exactly - and the #if selects the right one automatically!

"Everything depends on the native register size of the uProcessor."

It also depends on the specific compiler - different compilers for the same target might choose different sizes for some types...

Read-Only
Author
Drew Davis
Posted
3-Oct-2007 00:20 GMT
Toolset
C51
New! RE: Portable

it would have to have a condition to select the right definition for the particular compiler

Actually (as I'm sure Andy knows) you can just have a single header that differs for each particular compiler.

C99 calls it "inttypes.h".

It's probably easier to have one such header per compiler with a compiler-specific implementation than a single header with a long string of #if matching compiler-dependent preprocessor variables.

Read-Only
Author
Hans-Bernhard Broeker
Posted
3-Oct-2007 11:26 GMT
Toolset
C51
New! RE: Portable

C99 calls it "inttypes.h".

You mean <stdint.h>, of course.

Read-Only
Author
Drew Davis
Posted
3-Oct-2007 17:12 GMT
Toolset
C51
New! RE: Portable

Actually, I meant inttypes.h, but was simply wrong :)

Inttypes.h includes stdint.h, which is the file that actually defines the integer types. inttypes.h adds some extra definitions that you might not always need, so it would be better to include stdint.h directly.

Next Thread | Thread List | Previous Thread Start a Thread | Settings