I'm using MikroC for PIC, I don't know the name of the compiler. I'm using a PIC18F4550. I need to print a list of itens of a menu in a 16x4 LCD. I put here a slice of code, because the code is big to put it here, so, I tried to write here a minimal reproducible example.
The code works in the following whay: I have a stack to store the menus, the menu structure has fields as title and number of itens.
In file main.c
#include "menu.h"
int main(){
unsigned char error;
error = 0;
Tstack stackMenus;
error = menu_push(&stackMenus, &mainMenu);
}
=========================================================
In file menu.c
#include "menu.h"
const Tmenu mainMenu = {
4,
"Main Menu"
};
unsigned char menu_push( Tstack *s, PTmenu item ){
unsigned char error = 0;
if(s->topo == 9){
return 1;
}
s->pilha[++s->topo] = item;
return error;
}
======================================================
In file menu.h
struct Smenu {
unsigned char numberOfItens;
char *Title;
};
typedef struct Smenu Tmenu;
typedef Tmenu *PTmenu;
struct Sstack {
PTmenu stack[10];
signed char top;
};
typedef struct Sstack Tstack;
extern Tmenu mainMenu;
Terro menu_push(Tstack *s, PTmenu item);
I declared mainMenu as const, as pass it as argument to menu_stack. However, the compiler complains saying it is a "Illegal pointer conversion". I tryed to do
unsigned char menu_push( Tstack *s, Tmenu * const item ){ ...}
and
unsigned char menu_push( Tstack *s, const Tmenu * item ){ ...}
But the same message appears, "Illegal pointer conversion".
How can I handle that ? I need to declare the mainMenu as const because there are others menus and I'm using a microcontroller with a restricted RAM memory size.
This code compiles cleanly under reasonably stringent compilation options. There were quite a lot of trivial changes needed to convert your native language code to the translated English framework. However, I've eliminated PTmenu
as a type (as hinted in comments) — the answer to Is it a good idea to typedef pointers? is generally "No".
menu.h
typedef unsigned char Terro;
struct Smenu
{
unsigned char numberOfItens;
char *Title;
};
typedef struct Smenu Tmenu;
struct Sstack
{
const Tmenu *stack[10];
signed char top;
};
typedef struct Sstack Tstack;
extern const Tmenu mainMenu;
Terro menu_push(Tstack *s, const Tmenu *item);
main.c
#include "menu.h"
#include <stdio.h>
int main(void)
{
unsigned char error;
Tstack stackMenus = { { 0 }, 0 };
error = menu_push(&stackMenus, &mainMenu);
printf("Error = %d\n", error);
}
menu.c
#include "menu.h"
const Tmenu mainMenu =
{
4,
"Main Menu"
};
unsigned char menu_push(Tstack *s, const Tmenu *item)
{
unsigned char error = 0;
if (s->top == 9)
{
return 1;
}
s->stack[++s->top] = item;
return error;
}
Test compilation (to object file) with GCC 9.1.0 on a MacBook Pro running macOS 10.14.6 Mojave:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -c menu47.c
$
There are still issues with the code — the line if (s->top == 9)
is diabolical.
It should be more like if (s->top < 10)
except that the 10
should be a name the identifies the size of the stack
array in Tstack
— I'd probably use a variant on enum { STACK_SIZE = 10 };
and then use that in the array dimension and in the test. That name is a bit too generic for comfort — it could too easily collide with other stack sizes. But that depends on your use case and is taking us far afield. There should be header guards in the menu.h
file (#ifndef MENU_H_INCLUDED
/ #define MENU_H_INCLUDED
/ …contents of header… / #endif
). Capitalization of structure elements is haphazard. The variable error
in main()
should probably be of type Terro
. The return type of the function in menu.c
should match the declaration in menu.h
— it should be Terro
too. Etc.