Как передать массив символов в аргумент char **

#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] массив. Этот тип не может быть присвоен a char** , он же указатель на указатель на a char . Это разные типы.

4. Я исправлен. Если бы я подумал об этом больше, я бы понял, что array-> pointer decay приводит к rvalue char * , которое недопустимо для operatoramp;