I've noted that the following C code give "warning: initialization discards qualifiers from pointer target type" but it still compiles and behave as expected (outputting 'W' char).
#include <stdio.h>
int main(int argc, char *argv[])
{
char buffer[20] = {'H','e','l','l','o',' ','W','o','r','l','d','!','\0'};
const char* p = &buffer[0];
char* c = (p + 6);
printf("%c\n",*c);
}
In C++ rather similar code doesn't compile at all complaining about "error: invalid conversion from 'const char*' to 'char*' "
#include <iostream>
using namespace std;
int main()
{
char buffer[20] = {'H','e','l','l','o',' ','W','o','r','l','d','!','\0'};
const char* p = &buffer[0];
char* c = p + 6;
cout << *c;
cout << endl;
return 0;
}
What is the reason?
Is it possible to fix the C++ code to make it compile (and behave) like its C counterpart?
Better explanation: Thanks for all of your answers, but most of you didn't get my real problem so I'll try to explain in more details.
I'm using a library written in C. A function prototype in the header is something like:
void parse (const char* p, uint16_t len, uint8_t is_eof);
Inside the implementation of this function it happens to run code like
char* c = p + 6;
Everything is fine if I write my code in C and compile against this library.
Now I want to port this library in C++ since I need it in a C++ project. I successfully ported the library by redefining the function parameter as a variable rather than a constant. But since the p
pointer actually need NOT to change I'd prefer to define it as a constant, as is in the original C lib. Putting a variable rather than a constant I end up porting a library without preserving all the original semantics. This is bad since I can't know if the C++ library runs as well as the original C one.
I hope this is clear enough.
A (hopefully) even better explanation:
I'm following the tutorial in AVR Tutorials - [CODE][C] Parsing strings flexibly/efficiently with Ragel and the issue is relative to the parse_microscript()
function.
Since I'd like to embed Arduino code (that is, Serial.println();
) in the parser, I'm trying to compile this Ragel parser in a C++ host language, rather than C as proposed in the tutorial.
First, I try to include Arduino.h
in the generated C code, but the ArduinoIDE won't compile (I believe because of mixing C and C++ code).
I then tried to generate C++ code from the same Ragel script, but when compiling multiple "invalid conversion from 'const char*' to 'char*'" errors ar fired, targeting the generated code.
The only means to make it work in C++ had been to remove all constant keywords. This is bad since I'm changing the original semantic of the C code, but it works.
I tried to isolate the problem providing the above C and C++ snippets, but I probably poorly explained the point.
The accepted answer is what let the C++ snippet compile, but when I try this solution in Arduino code it doesn't work.
I put the working Ragel script compiled with the command ragel -G2 -o microscript.cpp microscript.rl
:
#include "qp_port.h"
#include "pelican.h"
#include "bsp.h"
#include "Arduino.h"
static uint16_t currentNumber;
%%{
machine microscript;
action ClearNumber {
currentNumber = 0;
}
action PrintNumber {
Serial.print("parameter: ");
Serial.println(currentNumber);
}
action RecordDigit {
uint8_t digit = (*p) - '0';
currentNumber = (currentNumber * 10) + digit;
}
number = ((digit @RecordDigit)+) > ClearNumber % PrintNumber;
whitespace = space+;
numlist = number (',' number)*;
crlf = '\r\n';
OK = crlf 'OK' crlf;
main := |*
crlf => {Serial.println("crlf");};
OK => {Serial.println("OK detected");};
*|;
}%%
%% Write data;
static uint8_t cs; /* The current parser state */
static char* ts;
static char* te;
static char* act;
void init_microscript() {
%% write init;
}
void parse_microscript(char* p, uint16_t len, uint8_t is_eof) {
char* pe = p + len; /* pe points to 1 byte beyond the end of this block of data */
char* eof = is_eof ? pe : ((char*) 0); /* Indicates the end of all data, 0 if not in this block */
%% write exec;
}
As you can see too, I had to change the first parameter of the parse_microscript
function from const char* p
to char*p
, and const char* pe
to char* pe
.
You can fix both of them by using the correct types:
const char* c = p + 6;
That's why you should treat C and C++ as separate languages.
You can cast away the const
:
char* c = (char*) p + 6;
But this is really a bad practice.
If you want to change a pointer why declare it as const?
If you want it to be a const
, why do you want to cast away the constness?
Ask the above questions and decide it yourself.
C++ is more strongly typed, C is not.
In C++ { 'H'...};
is a array of constant characters (ie const char *
). To initialize the variable buffer
the type needs to have the const
bit removed.
As C is not strongly typed it just issues a warning.
IMHO C++ is superior in this respect.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.