Разница в указателях между C и переполнением стека

Я заметил, что следующий код 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] Разбор строк гибко и эффективно с помощью Ragel и проблема относительно parse_microscript() функция.

Так как я хотел бы встроить код Arduino (то есть Serial.println();) в парсере я пытаюсь скомпилировать этот парсер Ragel на языке хоста C ++, а не на C, как предложено в руководстве.

Во-первых, я пытаюсь включить Arduino.h в сгенерированном коде C, но Arduino IDE не скомпилируется (я верю из-за смешивания кода на C и C ++).

Затем я попытался сгенерировать код на C ++ из того же сценария Ragel, но при компиляции нескольких ошибок «недопустимое преобразование из« 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,

1

Решение

Вы можете исправить и то и другое из них с использованием правильных типов:

const char* c = p + 6;
8

Другие решения

Вот почему вы должны рассматривать C и C ++ как отдельные языки.

Вы можете отбросить const :

   char* c = (char*) p + 6;

Но это действительно плохая практика

Если вы хотите изменить указатель, зачем объявлять его как const?
Если вы хотите, чтобы это было constзачем вы хотите выбросить это постоянство?

Задайте вышеуказанные вопросы и решите сами.

4

C ++ более типизирован, C — нет.

В C ++ { 'H' ...}; является массивом постоянных символов (т.е. const char *). Инициализировать переменную buffer тип должен иметь const немного удален

Поскольку C не является строго типизированным, он просто выдает предупреждение.

ИМХО С ++ лучше в этом отношении.

2
По вопросам рекламы [email protected]