简体   繁体   中英

Pointers difference between C and C++

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM