我注意到以下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 Tutorials - [CODE][C] Parsing strings flexibly/efficiently with Ragel中的教程,问题与parse_microscript()
函数有关。
由于我想在解析器中嵌入Arduino代码(即Serial.println();
),我试图用C ++宿主语言编译这个Ragel解析器,而不是像教程中提出的那样编译C语言。
首先,我尝试在生成的C代码中包含Arduino.h
,但Arduino IDE将无法编译(我相信因为混合了C和C ++代码)。
然后我尝试从相同的Ragel脚本生成C ++代码,但是当编译多个“从'const char *'到'char *'的无效转换”错误时,会触发生成的代码。
使其在C ++中运行的唯一方法是删除所有常量关键字。这很糟糕,因为我正在改变C代码的原始语义,但它可以工作。
我试图找出提供上述C和C ++代码片段的问题,但我可能很难解释这一点。
接受的答案是让C ++代码段编译的内容,但是当我在Arduino代码中尝试此解决方案时,它无效。
我使用命令ragel -G2 -o microscript.cpp microscript.rl
编译了工作的Ragel脚本:
#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
答案 0 :(得分:8)
您可以使用正确的类型修复两者:
const char* c = p + 6;
答案 1 :(得分:4)
这就是为什么你应该将C和C ++视为单独的语言。
你可以抛弃const
:
char* c = (char*) p + 6;
但这实际上是 不良做法。
如果要更改指针,为什么要将其声明为const?
如果你想让它成为const
,你为什么要抛弃常量?
提出上述问题并自行决定。
答案 2 :(得分:2)
C ++的类型更强,C不是。
在C ++中{ 'H' ...};
是一个常量字符数组(即const char *
)。要初始化变量buffer
,类型需要删除const
位。
由于C没有强类型,它只会发出警告。
恕我直言C ++在这方面是优越的。