指针C和C ++之间的区别

时间:2012-12-07 15:18:44

标签: c++ c pointers arduino ragel

我注意到以下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

3 个答案:

答案 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 ++在这方面是优越的。