#c
#c
Вопрос:
У меня есть одна функция, у которой есть аргумент в качестве char**
Мне нужно передать значение массива в том же аргументе, как я мог бы это передать?
int fun(char** val)
{
std::cout<<"val:"<<*val<<"n";
}
int main()
{
char ch[20];
strlcpy(ch, "test", sizeof(ch));
fun(amp;ch[0]) // here how can I pass the char array getting build issue
}
Комментарии:
1. Каков ожидаемый результат? И
strlcpy(ch, "test", sizeof(ch));
не имеет особого смысла, что вы ожидаете, чтоch
массив будет содержать после?2. @Jabberwocky это тоже
ch
неинициализировано. не уверен, что в CPP, в C, использованиеch
в качестве строки приведет к неприятностям.3.
int fun(char *val)
и затемfun(ch);
позволит вам передать массивch
вfun()
, который затем будет выводить первый символ, илиstd::cout << "val:"<<val<<'n';
для вывода всего содержимого.4.
strlcpy()
простоstrcpy()
с добавлением проверки границ, аналогичноstrncpy()
. Этот код копируется"test"
вch
.5. Почему это помечено C ? Я не вижу ничего, кроме
cout
…
Ответ №1:
Я думаю, что лучше всего выяснить, каково назначение функции fun
, на основе подписи, то есть типа параметра:
fun
принимает указатель на указатель на один символ или на начало группы символов. В первую очередь это означает, что fun
требуется иметь «ссылку» на указатель. Обычно это означает, что func
хочет изменить этот указатель и передать эту модификацию обратно вызывающему. Это швы val
на самом деле является параметром out, содержащим указатель. Если это действительно так, используйте эту подпись функции! В этом случае вы бы вызвали fun
таким образом:
char *c = NULL;
fun(amp;c);
// c is set by fun to a certain value
Если вы просто хотите распечатать символы, для читателя вашего кода намного проще и очевиднее изменить подпись fun
на
int fun(char *val) { /* ... */ }
Здесь говорится, что fun
принимает указатель на один символ или группу символов. Он получит этот указатель по значению, любая модификация самого указателя не будет видна за пределами fun
. В этом случае вы вызовете fun
с помощью
char c[] = "Hello World!";
fun(c);
Теперь, почему у вас возникла проблема со сборкой: тип amp;ch[0]
is char *
, то есть указатель на некоторые символы. Но ваш fun
ожидаемый char **
, то есть указатель на указатель на некоторые символы. Это явно проблема. И это также противоречит намерению, выраженному сигнатурой функции: fun
хочет иметь «ссылку» на указатель, чтобы изменить этот ссылочный указатель.
Редактировать: Итак, похоже, что вы застряли со странным API и вам нужно передать массив символов в функцию, ожидающую char **
параметра. В этом случае другие ответы предоставляют правильное, хотя и все еще сомнительное решение:
char c[] = "Hello World";
char *ptr = amp;c[0];
fun(amp;ptr);
ptr
Указывает на первый символ c
. Переменная ptr
сама по себе имеет адрес, а именно amp;ptr
, который имеет тип char **
. Итак, amp;ptr
это необходимая «ссылка» на указатель на набор символов, которые вы можете передать fun
.
Но имейте в виду тот факт, что fun
можно свободно изменять значение ptr
, т. е. сам адрес ptr
указывает на. Возможно, что при возврате из вызова fun
значение ptr
будет чем-то совершенно другим, указывающим на адрес, которого вы не ожидали. Черт возьми, возможно даже, что от вас ожидают вызова free(ptr)
в конце, даже если вы начали с адреса в ptr
некоторой статической памяти, к которой вы никогда не будете обращаться free()
. Чтобы узнать эти подробности, вы должны прочитать подробные спецификации функции fun
.
Комментарии:
1. Спасибо за ответ! Я знаю, что если у нас есть
fun(char* val)
иchar ch[]
, то мы можем передать какfun(ch)
. И еслиfun(char** val
иchar* ch
, то я могу сойти заfun(amp;ch)
. Моя проблема я использую один статический инструмент, который выдает проблему для проверки, необходимой дляfun
аргумента, и там я не могу передать, как я упоминал выше, и мне нужно передатьchar arr[]
вchar**
аргумент fun.
Ответ №2:
ch
является char[]
массивом. amp;ch[0]
разыменовывает массив для доступа к 1-му элементу, выдавая a char
, а затем берет адрес этого char
, выдавая a char*
. Но вместо этого функция хочет char**
. Поэтому сохраните это char*
в переменной и передайте адрес этой переменной функции, например:
int main()
{
char ch[20];
strlcpy(ch, "test", sizeof(ch));
char *ptr = ch; // same as: ptr = amp;ch[0]
fun(amp;ptr);
}
Комментарии:
1. Спасибо за ответ! Я знаю, что если у нас есть
fun(char* val)
иchar ch[]
, то мы можем передать какfun(ch)
. И еслиfun(char** val)
иchar* ch
, то я могу передать какfun(amp;ch)
. Моя проблема я использую один статический инструмент, который выдает проблему для проверки, необходимой дляfun
аргумента, и там я не могу передать, как я упоминал выше, и мне нужно передатьchar arr[]
вchar**
аргумент fun.2. @YogendraKumar нет способа напрямую передать
char[20]
фиксированный массивchar**
указателю, они разных типов. На что именно жалуется инструмент проверки?3. @Caleth
amp;ch
— этоchar(*)[20]
, он же указатель наchar[20]
массив. Этот тип не может быть присвоен achar**
, он же указатель на указатель на achar
. Это разные типы.4. Я исправлен. Если бы я подумал об этом больше, я бы понял, что array-> pointer decay приводит к rvalue
char *
, которое недопустимо дляoperatoramp;