Compile error

I am testing code on a 16x2 LCD.
using library HD44780 from Github @ GitHub - positronic57/HD44780Library: Library for connecting LCD with HD44780 controller to ARV 8-bit microcotrollers.
The code listed below compiles with one warning.

/*
   Connection between MCU and LCD:
   PORTB0 -> LCD D4
   PORTB1 -> LCD D5
   PORTB2 -> LCD D6
   PORTB3 -> LCD D7
   PORTD4 -> LCD RS
   PORTD6 -> LCD R/W
   PORTD7 -> LCD E

*/

#include <avr/io.h>
extern "C"  {
#include "HD44780.h"
}
//Define custom special characters. In this example those are  letters: a and b.

uint8_t specCharMatrix[2][8] = {{0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1F, 0x00}, {0x0E, 0x0A, 0x0A, 0x0A, 0x0A, 0x1F, 0x11, 0x00}};
//uint8_t i, j;
uint8_t numberOfSpecChars;
TSHD44780 HD44780Display;
TSHD44780 *pHD44780Display = &HD44780Display;
void setup() {

  /*
      Use:
      - TWO_LINES_DISPLAY to init 2 lines module;
      - FOUR_LINES_DISPLAY to init 4 lines LCD.

      Although single line LCD has only one line for presenting the content,
      the DDRAM memory in most of the modules out there is split in two 8 bytes long buffers.
      Those single line modules must be initialized using TWO_LINES_DISPLAY
      as argument of the init function. If that is not the case use
      SINGLE_LINE_DISPLAY during the init process.

  */
  LCDInit4(pHD44780Display, &PORTD, &PORTB, PD4, PD7, PD6, TWO_LINES_DISPLAY);
  //LCDDefineSpecialChars4(pHD44780Display, specCharMatrix, uint8_t numberOfSpecChars);

  LCDSendCommand4(pHD44780Display, DISPLAY_ON);

  LCDShowString4(pHD44780Display, "libHD44780");
  LCDSendCommand4(pHD44780Display, LCD16x2_SELECT_LINE_2);
  LCDShowString4(pHD44780Display, "Tester!!!");
}
/*
    To manually set the cursor position in case of single line LCD,
    use the strating addresses of the two 8 bytes
    wide DDRAM memory segments as base addresses.
    LCD16x1_SELECT_DDRAM_1ST_HALF
    LCD16x1_SELECT_DDRAM_2ND_HALF
*/


void loop() {
  LCDSetCursorPosition4(pHD44780Display, LCD16x2_SELECT_LINE_1, 12);
  //LCDSendCommand4(pHD44780Display, CURSOR_ON);
  //LCDSendCommand4(pHD44780Display, BLINKING_CURSOR_ON);
  //Show the data from the CGRAM

  LCDShowCharacter4(pHD44780Display, 0x33);
  LCDShowCharacter4(pHD44780Display, 0x21);
  //LCDDefineSpecialChars4( pHD44780Display,  (*specCharMatrix)[8], numberOfSpecChars);


  while (1)
  {

  }

However when i also include another function to display the specCharMatrix in the last line before the while statement, the compilation exits with an error.
This particular function is described in the libHD44780.c. This is

//Define custom special characters
void LCDDefineSpecialChars4(TSHD44780 *pHD44780,uint8_t (*charMatrix)[8],uint8_t numberOfSpecChars)
{
 uint8_t CGAddress = LCD_CGRAM_START_ADDRESS;
 uint8_t i,j;
 
 if (numberOfSpecChars>8)
 numberOfSpecChars=8;
 
 for(i=0;i<numberOfSpecChars;i++)
 for(j=0;j<8;j++)
 {
 //Set CGRAM address
 LCDSendCommand4(pHD44780,CGAddress++);
 //Write data to CGRAM
 LCDShowCharacter4(pHD44780,*(*(charMatrix+i)+j));
 }
 
 LCDSendCommand4(pHD44780,RETURN_CURSOR_HOME);
 
}

I have not been able to get around this error.
Regards for your time and help.

The complete error is > 9000 limit. so I am attaching the last portion only

.8.9\hardware -hardware C:\Users\Karanbir\AppData\Local\Arduino15\packages -hardware D:\Arduino_1.8.9\Portable\Sketchbook\hardware -tools D:\Arduino_1.8.9\arduino-1.8.9\tools-builder -tools D:\Arduino_1.8.9\arduino-1.8.9\hardware\tools\avr -tools C:\Users\Karanbir\AppData\Local\Arduino15\packages -built-in-libraries D:\Arduino_1.8.9\arduino-1.8.9\libraries -libraries D:\Arduino_1.8.9\Portable\Sketchbook\libraries -fqbn=MiniCore:avr:328:bootloader=uart0,variant=modelP,BOD=2v7,LTO=Os,clock=16MHz_external -ide-version=10809 -build-path C:\Users\Karanbir\AppData\Local\Temp\arduino_build_717389 -warnings=all -build-cache C:\Users\Karanbir\AppData\Local\Temp\arduino_cache_953306 -prefs=build.warn_data_percentage=75 -verbose D:\Arduino_1.8.9\Portable\Sketchbook\sketch_LCDTestGoceBoshkovski\sketch_LCDTestGoceBoshkovski.ino
Using board '328' from platform in folder: C:\Users\Karanbir\AppData\Local\Arduino15\packages\MiniCore\hardware\avr\2.0.2
Using core 'MCUdude_corefiles' from platform in folder: C:\Users\Karanbir\AppData\Local\Arduino15\packages\MiniCore\hardware\avr\2.0.2
Detecting libraries used...
"D:\\Arduino_1.8.9\\arduino-1.8.9\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Users\\Karanbir\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.0.2\\cores\\MCUdude_corefiles" "-IC:\\Users\\Karanbir\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.0.2\\variants\\standard" "C:\\Users\\Karanbir\\AppData\\Local\\Temp\\arduino_build_717389\\sketch\\sketch_LCDTestGoceBoshkovski.ino.cpp" -o nul
"D:\\Arduino_1.8.9\\arduino-1.8.9\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Users\\Karanbir\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.0.2\\cores\\MCUdude_corefiles" "-IC:\\Users\\Karanbir\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.0.2\\variants\\standard" "-ID:\\Arduino_1.8.9\\Portable\\Sketchbook\\libraries\\HD44780Library-GoceBoshkovski" "C:\\Users\\Karanbir\\AppData\\Local\\Temp\\arduino_build_717389\\sketch\\sketch_LCDTestGoceBoshkovski.ino.cpp" -o nul
Using cached library dependencies for file: D:\Arduino_1.8.9\Portable\Sketchbook\libraries\HD44780Library-GoceBoshkovski\HD44780.c
Generating function prototypes...
"D:\\Arduino_1.8.9\\arduino-1.8.9\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Users\\Karanbir\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.0.2\\cores\\MCUdude_corefiles" "-IC:\\Users\\Karanbir\\AppData\\Local\\Arduino15\\packages\\MiniCore\\hardware\\avr\\2.0.2\\variants\\standard" "-ID:\\Arduino_1.8.9\\Portable\\Sketchbook\\libraries\\HD44780Library-GoceBoshkovski" "C:\\Users\\Karanbir\\AppData\\Local\\Temp\\arduino_build_717389\\sketch\\sketch_LCDTestGoceBoshkovski.ino.cpp" -o "C:\\Users\\Karanbir\\AppData\\Local\\Temp\\arduino_build_717389\\preproc\\ctags_target_for_gcc_minus_e.cpp"
"D:\\Arduino_1.8.9\\arduino-1.8.9\\tools-builder\\ctags\\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\\Users\\Karanbir\\AppData\\Local\\Temp\\arduino_build_717389\\preproc\\ctags_target_for_gcc_minus_e.cpp"
Compiling sketch...
"D:\\Arduino_1.8.9\\arduino-1.8.9\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-                                               ^

D:\Arduino_1.8.9\Portable\Sketchbook\sketch_LCDTestGoceBoshkovski\sketch_LCDTestGoceBoshkovski.ino:61:46: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

   LCDShowString4(pHD44780Display, "Tester!!!");

                                              ^

D:\Arduino_1.8.9\Portable\Sketchbook\sketch_LCDTestGoceBoshkovski\sketch_LCDTestGoceBoshkovski.ino: In function 'void loop()':

sketch_LCDTestGoceBoshkovski:80:64: error: invalid conversion from 'uint8_t {aka unsigned char}' to 'uint8_t (*)[8] {aka unsigned char (*)[8]}' [-fpermissive]

   LCDDefineSpecialChars4( pHD44780Display,  (*specCharMatrix)[8], numberOfSpecChars);

                                                                ^

In file included from D:\Arduino_1.8.9\Portable\Sketchbook\sketch_LCDTestGoceBoshkovski\sketch_LCDTestGoceBoshkovski.ino:31:0:

D:\Arduino_1.8.9\Portable\Sketchbook\libraries\HD44780Library-GoceBoshkovski/HD44780.h:240:6: note:   initializing argument 2 of 'void LCDDefineSpecialChars4(TSHD44780*, uint8_t (*)[8], uint8_t)'

 void LCDDefineSpecialChars4(TSHD44780 *pHD44780,uint8_t (*charMatrix)[8],uint8_t numberOfSpecChars);

      ^

Using library HD44780Library-GoceBoshkovski in folder: D:\Arduino_1.8.9\Portable\Sketchbook\libraries\HD44780Library-GoceBoshkovski (legacy)
exit status 1
invalid conversion from 'uint8_t {aka unsigned char}' to 'uint8_t (*)[8] {aka unsigned char (*)[8]}' [-fpermissive]

Firstly, in C++ you are no longer allowed to pass string literals, like "Tester!!!" аs char * parameters. A "quick and dirty" way to fix this error would be

LCDShowString4(pHD44780Display, (char *) "Tester!!!");

Or you might choose to use a cleaner approach

char tester[] = "Tester!!!";
LCDShowString4(pHD44780Display, tester);

The second error is caused by a completely nonsensical code:

LCDDefineSpecialChars4( pHD44780Display,  (*specCharMatrix)[8], numberOfSpecChars);

It is not clear what was meant by this (*specCharMatrix)[8] as an argument. That makes no sense at all, given the parameter type. I would guess that the proper argument is simply specCharMatrix itself

LCDDefineSpecialChars4( pHD44780Display, specCharMatrix, numberOfSpecChars);

But since in the code the variable numberOfSpecChars is never assigned any meaningful value, there's no way to say whether this is correct or not. It is not clear whether one wants to pass the whole matrix (2 lines) or just some specific line.

You could also edit the library and change the argument type of LCDShowString4 to const char*.

// This line needs to change
void LCDShowString4(TSHD44780 *pHD44780,char *String2Show);

// To this
void LCDShowString4(TSHD44780 *pHD44780, const char *String2Show);

This change has to be made in both the .h and .c file.

Montmorency: The second error is caused by a completely nonsensical code:

LCDDefineSpecialChars4( pHD44780Display,  (*specCharMatrix)[8], numberOfSpecChars);

It is not clear what was meant by this (*specCharMatrix)[8] as an argument. That makes no sense at all, given the parameter type. I would guess that the proper argument is simply specCharMatrix itself

LCDDefineSpecialChars4( pHD44780Display, specCharMatrix, numberOfSpecChars);

But since in the code the variable numberOfSpecChars is never assigned any meaningful value, there's no way to say whether this is correct or not. It is not clear whether one wants to pass the whole matrix (2 lines) or just some specific line.

The intention is to display two special characters as defined in the code. Line no 36

uint8_t specCharMatrix[2][8] = {{0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1F, 0x00}, {0x0E, 0x0A, 0x0A, 0x0A, 0x0A, 0x1F, 0x11, 0x00}};

LightuC: You could also edit the library and change the argument type of LCDShowString4 to const char*

I did this change in the library files and the warning does not appear. Thanks Montmorency and LightuC for your deliberations It is nearly 2 AM in my area. will go to sleep. Will respond to your posts tomorrow :slight_smile:

kssoin: The intention is to display two special characters as defined in the code. Line no 36

uint8_t specCharMatrix[2][8] = {{0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x1F, 0x00}, {0x0E, 0x0A, 0x0A, 0x0A, 0x0A, 0x1F, 0x11, 0x00}};

In that case the proper way to call it would be

LCDDefineSpecialChars4(pHD44780Display, specCharMatrix, 2);

Or you can call it as

LCDDefineSpecialChars4(pHD44780Display, specCharMatrix, numberOfSpecChars);

but first make sure numberOfSpecChars is 2.

Montmorency:
In that case the proper way to call it would be

LCDDefineSpecialChars4(pHD44780Display, specCharMatrix, 2);

Or you can call it as

LCDDefineSpecialChars4(pHD44780Display, specCharMatrix, numberOfSpecChars);

but first make sure numberOfSpecChars is 2.

From the file libHD44780.c this is like

//Define custom special characters
void LCDDefineSpecialChars4(TSHD44780 *pHD44780,uint8_t (*charMatrix)[8],uint8_t numberOfSpecChars)
{
	uint8_t CGAddress = LCD_CGRAM_START_ADDRESS;
	uint8_t i,j;
	
	if (numberOfSpecChars>8)
		numberOfSpecChars=8;
		
	for(i=0;i<numberOfSpecChars;i++)
		for(j=0;j<8;j++)
		{
			//Set CGRAM address
			LCDSendCommand4(pHD44780,CGAddress++);
			//Write data to CGRAM
			LCDShowCharacter4(pHD44780,*(*(charMatrix+i)+j));
		}
	
	LCDSendCommand4(pHD44780,RETURN_CURSOR_HOME);
		
}

the two iterations with i and j indicate that the values of the matrix [2][8] are do be displayed one after the other.
The change as suggested does not yield the result in fact the special character display is blank.
Regards

kssoin: the two iterations with i and j indicate that the values of the matrix [2][8] are do be displayed one after the other.

The two iterations I suggested mean that 8 values from row specCharMatrix[0][0...7] are displayed, followed by 8 values from row specCharMatrix[1][0...7].

Exactly as intended, apparently.

Note also that *(*(charMatrix+ii)+jj) is exactly equivalent to charMatrix[ii][jj]. There's no reason to use that convoluted "pointer" syntax, when a plain [] will work just fine.

kssoin: The change as suggested does not yield the result in fact the special character display is blank.

Which means that the root of the problem is somewhere else.

Montmorency:
Which means that the root of the problem is somewhere else.

I have modified the code somewhat to get the desired results.
Thanks a ton Montmorency for guiding.If there is scope on refining it suggestions are welcome
The final code is

/*
   libHD44780.c

   Created: 13-Jun-15 13:58:22
   Author: Goce Boshkovski

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License.

   Example of using HD44780 library on Atmega32.The CPU freq is 4MHz defined with F_CPU.
   is being compiled for Atmega328 The CPU freq is 1MHz defined with F_CPU
   on 16-April-219

   JHD 162A 16x2 LCD module is used for the test.
   Standard LCD from extreme electronic is being used instead.
*/
/*
   Connection between MCU and LCD:
   PORTB0 -> LCD D4
   PORTB1 -> LCD D5
   PORTB2 -> LCD D6
   PORTB3 -> LCD D7
   PORTD4 -> LCD RS
   PORTD6 -> LCD R/W
   PORTD7 -> LCD E

*/

#include <avr/io.h>
extern "C"  {
#include "HD44780.h"
}
//Define custom special characters. In this example those are  letters: a and b.

uint8_t specCharMatrix[2][8] = {{0x21, 0x22, 0x23, 0x24, 0x25, 0x7B, 0x7D, 0x2A}, {0x2B, 0x2D, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D}};

uint8_t numberOfSpecChars;
TSHD44780 HD44780Display;
TSHD44780 *pHD44780Display = &HD44780Display;
void setup() {
  /*
      Use:
      - TWO_LINES_DISPLAY to init 2 lines module;
      - FOUR_LINES_DISPLAY to init 4 lines LCD.

      Although single line LCD has only one line for presenting the content,
      the DDRAM memory in most of the modules out there is split in two 8 bytes long buffers.
      Those single line modules must be initialized using TWO_LINES_DISPLAY
      as argument of the init function. If that is not the case use
      SINGLE_LINE_DISPLAY during the init process.

  */
  LCDInit4(pHD44780Display, &PORTD, &PORTB, PD4, PD7, PD6, TWO_LINES_DISPLAY);
  LCDDefineSpecialChars4(pHD44780Display, specCharMatrix, 8);

  LCDSendCommand4(pHD44780Display, DISPLAY_ON);

  LCDShowString4(pHD44780Display, "libHD44780");
  LCDSendCommand4(pHD44780Display, LCD16x2_SELECT_LINE_2);
  LCDShowString4(pHD44780Display, "Tester!!!");
}
/*
    To manually set the cursor position in case of single line LCD,
    use the strating addresses of the two 8 bytes
    wide DDRAM memory segments as base addresses.
    LCD16x1_SELECT_DDRAM_1ST_HALF
    LCD16x1_SELECT_DDRAM_2ND_HALF
*/


void loop() {

  LCDSetCursorPosition4(pHD44780Display, LCD16x2_SELECT_LINE_1, 11);
  //LCDSendCommand4(pHD44780Display, CURSOR_ON);
  //LCDSendCommand4(pHD44780Display, BLINKING_CURSOR_ON);
  //Show the data from the CGRAM


  uint8_t i, j;

  if (numberOfSpecChars > 8)
    numberOfSpecChars = 8;


  for (i = 0; i < 1; i++)
    for (j = 0; j < 4; j++)
    {

      LCDShowCharacter4(pHD44780Display, specCharMatrix[+i][+j]);
      _delay_ms(1000);
    }

  LCDSetCursorPosition4(pHD44780Display, LCD16x2_SELECT_LINE_2, 11);
  //LCDSendCommand4(pHD44780Display, CURSOR_ON);
  //LCDSendCommand4(pHD44780Display, BLINKING_CURSOR_ON);

  for (i = 0; i < 1; i++)
    for (j = 4; j < 8; j++)
    {
      //Set CGRAM address
      //LCDSendCommand4(pHD44780,CGAddress++);
      //Write data to CGRAM
      LCDShowCharacter4(pHD44780Display, specCharMatrix[+i][+j]);
      _delay_ms(1000);
    }
  LCDSetCursorPosition4(pHD44780Display, LCD16x2_SELECT_LINE_1, 11);
  //LCDSendCommand4(pHD44780Display, CURSOR_ON);
  //LCDSendCommand4(pHD44780Display, BLINKING_CURSOR_ON);
  for (i = 1; i < 2; i++)
    for (j = 0; j < 4; j++)
    {
      //Set CGRAM address
      //LCDSendCommand4(pHD44780,CGAddress++);
      //Write data to CGRAM
      LCDShowCharacter4(pHD44780Display, specCharMatrix[+i][+j]);
      _delay_ms(1000);
    }

  LCDSetCursorPosition4(pHD44780Display, LCD16x2_SELECT_LINE_2, 11);
  //LCDSendCommand4(pHD44780Display, CURSOR_ON);
  //LCDSendCommand4(pHD44780Display, BLINKING_CURSOR_ON);
  for (i = 1; i < 2; i++)
    for (j = 4; j < 8; j++)
    {
      //Set CGRAM address
      //LCDSendCommand4(pHD44780,CGAddress++);
      //Write data to CGRAM
      LCDShowCharacter4(pHD44780Display, specCharMatrix[+i][+j]);
      _delay_ms(1000);
    }


}

Now the sixteen characters defined in the [2][8] array are displayed as desired.
In this guided excercise I got clarity on this matrix and addressing its contents.

Firstly, in C++ you are no longer allowed to pass string literals, like "Tester!!!" аs char * parameters.

This statement is nonsense. You CAN pass a string literal to a function. The key is to understand that the string literal's type is const char *, not char *. That is NOT a change.

If the function is properly written, it will declare its argument as const char *. After all, why would LCDShowString4() expect that it should be allowed to modify the passed in string? It should make it quite clear that it will NOT modify the input string by making the argument const char *.

If the function is written by a hack, who doesn't understand that he/she should promise not to modify the input string, then I wouldn't use the function. If using the function is unavoidable, then the string literal can be cast to a char *, but bad things will happen when the function tries to alter the string.

PaulS: This statement is nonsense. You CAN pass a string literal to a function. The key is to understand that the string literal's type is const char *, not char *. That is NOT a change.

If the function is properly written, it will declare its argument as const char *. After all, why would LCDShowString4() expect that it should be allowed to modify the passed in string? It should make it quite clear that it will NOT modify the input string by making the argument const char *.

If the function is written by a hack, who doesn't understand that he/she should promise not to modify the input string, then I wouldn't use the function. If using the function is unavoidable, then the string literal can be cast to a char *, but bad things will happen when the function tries to alter the string.

This is C code which is now being compiled on the Arduino platform. This has been addressed if you go through the previous posts.

Why are you getting angry ? But it is your business I choose not to be drawn in your deliberations. Everybody does not have "Your" expertise. But does this give you the privilege to label others on the learning curve as Hacks ? Where has civility gone....?

Why are you getting angry ?

I am not getting angry at you. I am getting angry at Montmorency who keeps spouting nonsense on the forum.

Where has civility gone....?

The same place the intelligence of the person that wrote the function that you are trying to use.

When a function takes a pointer, the function should define whether or not it will modify the data pointed to.

If it says that it will modify the data, then the caller needs to know to not call the function with a string literal that can not be modified.

If it says that it will not modify the pointed to data, by using the const keyword in the argument definition, then you can call the function with a string literal.

If the programmer couldn't be bothered, then I wouldn't use the function or the library or buy anything else from the company that supplied the library.

But, then, that could be just because I'm tired of getting burned. YMMV.

PaulS: I am not getting angry at you. I am getting angry at Montmorency who keeps spouting nonsense on the forum. The same place the intelligence of the person that wrote the function that you are trying to use.

When a function takes a pointer, the function should define whether or not it will modify the data pointed to.

If it says that it will modify the data, then the caller needs to know to not call the function with a string literal that can not be modified.

If it says that it will not modify the pointed to data, by using the const keyword in the argument definition, then you can call the function with a string literal.

If the programmer couldn't be bothered, then I wouldn't use the function or the library or buy anything else from the company that supplied the library.

But, then, that could be just because I'm tired of getting burned. YMMV.

I am testing code on a 16x2 LCD. using library HD44780 from Github @ https://github.com/positronic57/HD44780Library

The functions are from this repository.

//Display a string on the LCD
void LCDShowString4(TSHD44780 *pHD44780,char *String2Show)
{
    while(*String2Show)
    LCDShowCharacter4(pHD44780,*String2Show++);
}

So, the function takes a string that it does not promise it won't modify. It then passes the characters, one at a time, by value to a function that can not possibly change the character.

So, there is nothing in this code that changes the pointed to string. So, the function SHOULD have been declared:

void LCDShowString4(const TSHD44780 *pHD44780, const char *String2Show);

and the implementation of the function should have used the same signature.

PaulS: This statement is nonsense. You CAN pass a string literal to a function.

Um... You are seriously confused and need some "Reading in Comprehension 101" classes. Let me repeat my statement again:

In C++ you are no longer allowed to pass string literals, like "Tester!!!" аs char * parameters.

It is a strange thing I have to resort to this, but apparently it is necessary. Read it and try to understand what it says.

(And I'll help you). It simply says that the proper way to pass string literals is const char * (one possible way), not char *. It also hints at the fact that back in C++98 days you were actually allowed to implicitly convert string literals to char * type. Hence "no longer". You can still find a lot of older code that attempts to rely on that permission (the one we are dealing with might be an example).

PaulS: The key is to understand that the string literal's type is const char *, not char *. That is NOT a change

Oh, I'm glad you got my message. But a little correction:

No, string literals are NOT of type const char *. In C++ string literals are of type const char [N], where N is the size of array needed to represent the string. That's quite a difference from const char *. This difference is not very important in this context, but is quite important in others.

PaulS: I am not getting angry at you. I am getting angry at Montmorency who keeps spouting nonsense on the forum.

This "nonsense" I'm "spouting" is called C++ programming language, dear. It is a complicated language and I understand that to an unprepared person it might sound a bit like "nonsense" at first. But there's quite a bit of effort and good logic that went into the design of this language. Not "nonsense" at all. You are making your first steps in understanding it, so it is OK to feel a bit overwhelmed at first.

Let me repeat my statement again:

In C++ you are no longer allowed to pass string literals, like "Tester!!!" аs char * parameters.

That statement IS nonsense. There are several ways that you can do that. Casting the literal to a char * is one way, but that doesn't change the fact that what is passed is a pointer to a string literal.

It simply says that the proper way to pass string literals is const char * (one possible way)

A string literal is pointed to by a const char *. There is no getting around that fact. The function that you are passing the pointer to expects that, or it doesn't. There is no getting around that fact, either.

In C++ string literals are of type const char [N], where N is the size of array needed to represent the string. That's quite a difference from const char *. This difference is not very important in this context, but is quite important in others.

I know the difference between a char array and a char pointer. I agree that, in this context, the distinction is not important.

This "nonsense" I'm "spouting" is called C++ programming language, dear.

Don't call me dear. And, I wasn't commenting on just this thread.

Not "nonsense" at all.

The language is not. Your interpretation of some code, and resulting behavior, is.

You are making your first steps in understanding it

I've been using C++ for more than 20 years.

PaulS: That statement IS nonsense. There are several ways that you can do that. Casting the literal to a char * is one way, but that doesn't change the fact that what is passed is a pointer to a string literal.

Wow! You ripped my original statement out of context. A context that was explaining all that, including the possibility to cast to explicitly cast to char * (!)

And now you are stealing my statements from that context to pass as your own. O_o

PaulS: A string literal is pointed to by a const char *. There is no getting around that fact.

Um... You are already contradicting yourself. Just a second ago you clearly (and correctly) stated that there is a way to get around that fact: casting it to char *. What gives?

PaulS: The function that you are passing the pointer to expects that, or it doesn't. There is no getting around that fact, either.

Um... Welcome to the real world. I'm a huge fan of const correctness, but unfortunately there are copious amounts of functions out there that receive their input as pointers (or references) to modifiable data, even though they don't intend to modify it. C code suffers from this issue more often than C++ code, but both are guilty.

In this case the fact is we are doing with third-party code from a repository (read: a code that we should not really modify) that suffers from this unfortunate problem.

PaulS: The language is not. Your interpretation of some code, and resulting behavior, is. I've been using C++ for more than 20 years.

Great. But alas I've seen people who "used" the language for even longer periods of time, but... you know... never really cared to learn it properly.

Um... You are already contradicting yourself. Just a second ago you clearly (and correctly) stated that there is a way to get around that fact: casting it to char *. What gives?

You can't get around the fact that a string literal is pointed to by a const char *. You can pretend that a const char * is a char *, when passing the pointer to a function that expects a pointer to char BUT that doesn't actually intend to modify the char array pointed to.

Trying to pretend that a const char * is a char *, when the function DOES actually modify the pointed to array is a recipe for disaster.

In this case the fact is we are doing with third-party code from a repository (read: a code that we should not really modify) that suffers from this unfortunate problem.

The fact is that OP does not NEED to use this function. OP might want to, because it is easy. But, then OP needs to be prepared to deal with the fact that the function is poorly declared.

But alas I've seen people who "used" the language for even longer periods of time, but... you know... never really cared to learn it properly.

That wouldn't be me. I don't keep the references handy, so I occasionally get a fact (or two) wrong. But I do understand pointers and arrays and casting, and what casts are valid and what casts are not. I can recognize a poorly written/not well tested function when I see it.

PaulS: You can't get around the fact that a string literal is pointed to by a const char *. You can pretend that a const char * is a char *, when passing the pointer to a function that expects a pointer to char BUT that doesn't actually intend to modify the char array pointed to.

Trying to pretend that a const char * is a char *, when the function DOES actually modify the pointed to array is a recipe for disaster.

Trying to modify a const object through a non-const access path is a disaster. It leads to undefined behavior. Nobody here is arguing with that. But however true that is, this is not germane to the situation at hand. Nobody is trying to modify string literals here. I don't know why you keep bringing this up.

And yes, you can "pretend" that a string literal is a char *. C++ language (as well as C) provides a very clear separation between:

  1. The act of generating a non-constant access path (a pointer or a reference) to a constant object.
  2. The act of actually trying to modify a constant object through that non-constant access path.

In C and C++ you are allowed to forcefully cast away constness from constant objects (step 1) as much as you want. The behavior is well-defined by the language. You are allowed to do it, as long as you don't make any modification attempts (step 2).

Nobody is trying to modify string literals here. I don't know why you keep bringing this up.

Since the function is trying to modify the value pointed to, the function should promise not to do that. THAT is what the discussion is about. Since it did not, then the discussion began to focus on how to get around that.

PaulS: Since the function is trying to modify the value pointed to, the function should promise not to do that. THAT is what the discussion is about. Since it did not, then the discussion began to focus on how to get around that.

It definitely should! Nobody's arguing with that either. But let me repeat what I already said above

"I'm a huge fan of const correctness, but unfortunately there are copious amounts of functions out there that receive their input as pointers (or references) to modifiable data, even though they don't intend to modify it. C code suffers from this issue more often than C++ code, but both are guilty."

Authors of that third-party library should definitely update their code. But I don't think that telling the OP what authors of that third-party library "should" do can help the OP much.