0

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.

Daniel
  • 107
  • 6
  • 1
    This question needs a [mcve]. In other words, give us a complete, but minimal, set of code (with no `...`) so that we can reproduce the problem. – user3386109 Jul 25 '19 at 16:14
  • BTW, I just put together a [mcve] based on the code in the question, and it works fine. – user3386109 Jul 25 '19 at 16:21
  • 1
    The third notation — `Terro menu_stack( ..., const Tmenu * item ){ ...}` should be usable as long as the prototype is in scope before the call is made. Did you change the header as well as the function definition? – Jonathan Leffler Jul 25 '19 at 16:50
  • @JonathanLeffler, yes. It is in a .h file that was included. I will update the post to meet the minimal reproducible example cited above. – Daniel Jul 25 '19 at 16:56
  • 1
    The message "illegal pointer conversion" isn't one I recognize, so it probably isn't GCC that you're using. Which compiler are you using? The most likely error from GCC would be "conversion discards const qualifier" or thereabouts. – Jonathan Leffler Jul 25 '19 at 17:05
  • @JonathanLeffler, I'm using MikroC for PIC, I don't know the name of the compiler. I'm using a PIC18F4550 – Daniel Jul 25 '19 at 17:16
  • 1
    See [Is it a good idea to typedef pointers?](https://stackoverflow.com/questions/750178/is-it-a-good-idea-to-typedef-pointers) — TL;DR, the answer is generally "No" with possible exceptions for function pointers. Mixing `const` with `PTmenu` will give you headaches (it gives me headaches); don't do it. Roughly: `const PTmenu` is the same as `Tmenu * const`, IIRC. Use the explicit `const Tmenu *` notation. – Jonathan Leffler Jul 25 '19 at 18:10
  • @JonathanLeffler, I did it. I suspected that too, but this made no difference. – Daniel Jul 25 '19 at 18:51

1 Answers1

1

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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thank you very much! Was very kind of you to compile the code. As I said, I already tried to compile without use a pointer as a type. But I did it for some variables, not all. Now, that you reaffirmed this issue, I did it again, but now I eliminated all typedef pointers of the code. The code not compiles yet, but the message changed, now appears: "initialization image not found for mainMenu". I don't know why it is happening, but I think it happened because I initialized mainMenu outside of any function. Could be it the problem ? – Daniel Jul 26 '19 at 12:32
  • But, I need to create it outside a function because the menus need to be global. And if I do it const I can't modify it inside a function after creation. – Daniel Jul 26 '19 at 12:42
  • I solved the last problem, initialization image not found for mainMenu. It was different in declaration in .h and .c . Sorry. – Daniel Jul 26 '19 at 12:53