0

I'm programming 8051 microcontroller using keil C51 C compiler, which only support C90.

I want to send a byte of data via UART, the function look like this:

void Uart_send(char data){
   //...
}

Use 1:

char a = 123;
Uart_send(a); //work great

Use 2:

Uart_send(123);//doesn't work, but no error or warning from compiler

In the latter case, 1 byte is sent, but not the correct value (123).

If I change my code to:

void Uart_send(const char data){
   //...
}

Then everything works perfectly.

From my understanding and several sources on the internet, the only purpose of "const" is to prevent the function from changing its argument (in other words, to prevent the programmer from changing argument by mistake). Then why does my second method not work?

Edit: This is my full code:

UART.h

typedef struct {
    char Buffer[10];
    char *p;
    char Ready;
    void (*Load)(char Data);
    void (*Transmit)();
    void (*Flush)();
} _uart;
extern _uart UART;

UART.c

#include "UART.h"
#include <reg51.h>

#define EOF 0x00
/*
0000_0000: EOF
0000_0001: countdown
1xxx_xxxx: primary time set
1xxx_xxxx: secondary time set
0111_xxxx: set phase

*/
#define Wait() for(i = 0; i < 3; ++i)
void Load(const char Data){
    *UART.p = Data;
    if(Data == EOF){
        UART.Ready = 1;
    }
    ++UART.p;
}
void Transmit(){
    int i;
    char *p;
    p = UART.Buffer;
    while(1){
        SBUF = *p;
        while(~TI);
        TI = 0;
        Wait();//make sure slave finish process data before sending next byte
        if(*p == EOF) break;//we are done
        ++p;
    }
    UART.Flush();
}
void Flush(){
    UART.p = UART.Buffer;
    UART.Ready = 0;
}
_uart UART = {
    {EOF, EOF, EOF, EOF, EOF, EOF, EOF, EOF, EOF, EOF},
    UART.Buffer, 0,
    Load,
    Transmit,
    Flush
};

main.c

#include "UART.h"
//.....
UART.Load(123);
UART.Load(0x00); //0x00 = EOF
UART.Transmit();
namcao00
  • 272
  • 1
  • 6
  • 10
  • `Uart_send(123)` shouldn't be a problem. Can you please elaborate on the "doesn't work" part? What value *is* being "sent"? – Some programmer dude Oct 04 '18 at 11:18
  • Do you have a prototype for `Uart_send()` in scope? – pmg Oct 04 '18 at 11:19
  • How is `Uart_send` declared? I assume you include a header to call it, how is it declared there? – StoryTeller - Unslander Monica Oct 04 '18 at 11:19
  • 1
    Not in C, @Blaze. `const` qualified objects are not really "constant". – pmg Oct 04 '18 at 11:24
  • AFAICT Your code should behave exactly the same in any C compiler. Are your actual code referring to a const pointer perhaps? – Lie Ryan Oct 04 '18 at 11:25
  • So that's just a C++ thing, then? I didn't know that. And another valuable thing learned today. Thanks! :) – Blaze Oct 04 '18 at 11:26
  • As for the "purpose" of `const` arguments, beside what's mentioned it's also tells the caller *intent* of the function, and makes code easier to understand and use and maintain. – Some programmer dude Oct 04 '18 at 11:26
  • 1
    In retrospect, I think `const` should have been named `"readonly"` (quotes included to mark as inexistent). – pmg Oct 04 '18 at 11:27
  • 1
    @Blaze For `case` only compile-time constants can be used. A `const` argument can't be a compile-time constant in C++ either. – Some programmer dude Oct 04 '18 at 11:28
  • @pmg - Or perhaps it should have been made a full-measure and produced integral constant expressions, like it in C++. – StoryTeller - Unslander Monica Oct 04 '18 at 11:31
  • @Someprogrammerdude I see. Thanks. – Blaze Oct 04 '18 at 11:34
  • 1
    @StoryTeller: that would work too :) – pmg Oct 04 '18 at 11:35
  • 1
    In the code you have shown, there is a difference between the `Load` function pointer in the `_uart` `struct`, and actual function `Load` – sp2danny Oct 04 '18 at 11:40
  • @sp2danny I made a mistake there. However this code work perfectly – namcao00 Oct 04 '18 at 11:43
  • Your "full code" is really not related to the initial code and the problems it might have. Please read about [how to ask good questions](http://stackoverflow.com/help/how-to-ask), as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). Lastly learn how to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve). – Some programmer dude Oct 04 '18 at 11:44
  • "8051 microcontroller using keil C51" Why not use something from the current millennium instead? Those old Keil compilers were almost as horrible as the 8051 core. Luckily, better tools arrived in the 1990s. – Lundin Oct 04 '18 at 14:06

2 Answers2

5

Now when we can see your code the problem is clear: You don't have a function declaration (a prototype) in the header file.

In C you really need to declare things before you can use them, otherwise the compiler will not know about them.

Note that there's a big difference between standard editions here. In older C standards (before C99) using a function would implicitly declare by deducing the argument types from the call (which in your case would have been wrong since 123 is an int). From C99 and onward that's not really allowed anymore.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
2

Purpose of const argument other than avoiding mistake

Compiler can do some optimizations with the const present.

pmg
  • 106,608
  • 13
  • 126
  • 198