Здравствуйте. У меня такая проблема, я хочу передать в функцию параметр const char **, но компилятор выдает ошибку, на Си это проходит без проблем, а на Си++ пишет "cannot conver parametr 1 from 'char **' to 'const char **'. В чем проблема, что я делаю не так ? Вот исходник: #include <iostream> using namespace std; int sumoflen(const char **words, const int N); int main(int argc, char **argv) { const int size = 256; int N; int i = 0; cin >> N; cin.get(); char **mywords = new char*[N]; for (i = 0; i < N;i++) mywords = new char[size-1]; while(i < N) cin.getline(mywords[i++],size - 1); cout << sumoflen(mywords, N) << endl; return 0; } int sumoflen(const char **words,const int N) { int i; int sum = 0; for (i = 0; i < N; i++ ) sum += strlen(words); return sum; }
Код (Text): #include <iostream> #include <string> #include <vector> size_t sumoflen(const std::vector<std::string> & v) { size_t retval = 0; for (std::vector<std::string>::const_iterator it = v.begin(), end = v.end(); it < end; ++it) { retval += (*it).size(); } return retval; } int main(int argc, char ** argv) { enum { size = 256 }; size_t N; std::cin >> N; std::cin.get(); std::vector<std::string> v(N); for (size_t i = 0; i < N; ++i) { char array[size]; std::cin.getline(array, size - 1); std::string s(array); v.push_back(s); } std::cout << sumoflen(v); } /* [EOF] */ Ы? Ж)
censored Ну интересная версия, тогда можно было передать и const string[], но меня интересует, можно ли именно const char **
REASY Код (Text): void foo(const char**) {} void main() { char a[1][1]; foo(reinterpret_cast<const char**>(&a[0][0])); }
censored После вызова sumoflen(reinterpret_cast<const char **>(&mywords[0][0]), N); получается так, что const char **words указывает на адреса, и если мы набрали допустим 12345, то i-тый элемент указывает на ячейку по адресу 0x34333231. Т.е. words[0] = значение по адресу 0x34333231.
REASY Это разные типы. В случае char* => const char* возможно неявное преобразование (char => const char), а в случае char** => const char** это уже нельзя, т.к. типы разные. Нагляднее разница видна здесь: Код (Text): typedef char* LPSTR; typedef const char* LPCSTR; void f(const LPCSTR*); void g(const LPSTR*); void test() { LPSTR pp = 0; f(pp); // cannot convert LPSTR* to LPCSTR* g(pp); // ok }
const char не запрещает изменения. Компилер просто выдает варнинги при компиляции в отлад целях. По стандарту. Если реализовано. Если стоит нужный уровень варнингов. А в случае const char ** вы, скорей всего, и варнингов не увидите.
REASY, если ты перед переменной поставил const, то все, это значит, что переменная ВСЕГДА будет иметь тот параметр, который ты ей передал в момент объявления. Код (Text): const int size = 256; ... mywords[i] = new char[size-1]; сдесь ты пытаешься изменить то, что не изменяемо. Раз ошибка. То же самое, как объявить: Код (Text): #define x 5 x теперь всегда будет 5. И все попытки изменения, вызовут ошибку. Давай разберемся. 1. Объявил функцию, которая принимает два параметра типа const: сhar и int. 2. Вызываешь ее и передаешь ей в качестве параметров два значения, mywords и N. 3. mywords - указатель на вновь создаваемый динамический тип (не const с позиции компилятора). Два ошибка. И что - то мне подсказывает, что есть еще ошибки, я не стал смотреть дальше.
probka Код: const int size = 256; mywords = new char[size-1]; Здесь я только выделяю память 255 байт для слова, причем тут "ы пытаешься изменить то, что не изменяемо", что то я не пойму. Я тут пошел по методу, когда передают фу-и const char *,но вместо этого я захотел передать фу-и массив слов(char **), но мне уже сказали, что "В случае char* => const char* возможно неявное преобразование (char => const char), а в случае char** => const char** это уже нельзя, т.к. типы разные".
_basmp_ Вот что пишет С. Прата в примечании к одной из программ: Код (Text): int c_in_str(const char *str, char ch) { int count = 0; whie(*str) { if (*str == ch) count ++; str++; } return count; } Поскольку фу-я c_in_str не должна вносить изменения в исходную строку, она использует спецификатор const при описании формального параметра str....
_basmp_ Именно запрещает, на уровне языка. Правда, это можно обойти приведением типа, но тогда кодер - сам себе злобный буратино, ибо данные могут быть в RO-памяти. C2166 в случае VC мало похож на предупреждение. Как и "error: expression must be a modifiable lvalue" в случае Comeau.
Ну ты же изменяешь значение НЕИЗМЕНЯЕМОЙ переменной " size-1 ": Код (Text): mywords[i] = new char[size-1] Как можно это делать, если явно, в самом начале, сказал компилятору: значение переменной size - постоянно " const int size = 256 ; ", ВСЕГДА! И зачем у тебя - ' ** '? Что, нельзя просто передать массив по ссылке - ' * '? Зачем понадобилась ссылка на ссылку? И еще, объявляешь массив динамически, и не говоришь, какой объем выделить. Интересная запись: Код (Text): char **mywords = new char*[N]; Вот так правильнее: Код (Text): char *mywords = new char;
Нельзя приводить const к не const, обратное можно. Константность это свойство переменной. Компилятору пофиг будут или нет изменять неконстантную переменную, он просто не даёт присвоить неконстантной константную. Конечно константные могут быть оптимизированы, то есть заранее зашиты в секцию данных ReadOnly.
REASY Если вкратце - объяви функцию sumoflen следующим образом: Код (Text): int sumoflen(const char * const*words, const int N); Подробнее - http://www.parashift.com/c++-faq-lite/const-correctness.html probka Код корректен, строка "mywords = new char[size-1]" не изменяет size, ссылка на ссылку понадобилась потому, что mywords - это не одна строка, а массив строк, то есть массив массивов, запись "char **mywords = new char*[N];" в этом контексте абсолютно правильна.
Возможно. Никогда не придавал этому большого значения. Просто привожу типы и все. кстати говоря const char ** это что: (const char) ** (const (char *)) * const (char **) Заранее прошу прощения за свою тупость и безграмотность. Все это так. Но только на бумаге (см замечание от IceStudent). нет. такой гарантии нет. Те (const int i=5 != (#define i 5).
_basmp_ Первое. Для последнего нужно писать либо "char** const", либо "typedef char** LPPSTR; const LPPSTR".