我注意到以下 C 代码给出“警告:初始化丢弃指针目标类型的限定符”,但它仍然可以编译并按预期运行(输出 'W' 字符)。
#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);
}
在 C++ 中,类似的代码根本无法编译并抱怨“错误:从 'const char*' 到 '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;
}
是什么原因?
是否可以修复 C++ 代码以使其像 C 对应物一样编译(和行为)?
更好的解释:感谢您的所有回答,但你们中的大多数人没有得到我真正的问题,所以我会尝试更详细地解释。
我正在使用用 C 编写的库。标题中的函数原型类似于:
void parse (const char* p, uint16_t len, uint8_t is_eof);
在这个函数的实现中,它碰巧运行了类似的代码
char* c = p + 6;
如果我用 C 编写代码并针对这个库进行编译,一切都很好。
现在我想在 C++ 中移植这个库,因为我在 C++ 项目中需要它。通过将函数参数重新定义为变量而不是常量,我成功地移植了库。但由于p
指针实际上不需要更改,我更愿意将其定义为常量,就像在原始 C lib 中一样。放置一个变量而不是一个常量,我最终会在不保留所有原始语义的情况下移植一个库。这很糟糕,因为我不知道 C++ 库是否与原始 C 库运行得一样好。
我希望这足够清楚。
一个(希望)更好的解释:
我正在学习 AVR 教程中的教程 - [CODE][C] 使用 Ragel 灵活/高效地解析字符串,问题与parse_microscript()
函数有关。
因为我想在解析器中嵌入 Arduino 代码(即Serial.println();
),所以我尝试用 C++ 宿主语言而不是教程中建议的 C 来编译这个 Ragel 解析器。
首先,我尝试包含Arduino.h
在生成的 C 代码中,但 Arduino IDE无法编译(我相信是因为混合了 C 和 C++ 代码)。
然后我尝试从同一个 Ragel 脚本生成 C++ 代码,但是在编译多个“从 'const char*' 到 'char*' 的无效转换”时,针对生成的代码触发了错误。
使它在 C++ 中工作的唯一方法是删除所有常量关键字。这很糟糕,因为我正在更改 C 代码的原始语义,但它确实有效。
我试图通过提供上述 C 和 C++ 代码片段来隔离问题,但我可能很难解释这一点。
公认的答案是让 C++ 片段编译的原因,但是当我在 Arduino 代码中尝试这个解决方案时它不起作用。
我将使用以下命令编译的工作 Ragel 脚本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;
}
正如您所看到的,我不得不将parse_microscript
函数的第一个参数从 const更改char* p
为char*p
,再更改const char* pe
为char* pe
。