Я читал несколько обсуждений передачи char * в C.
stackoverflow: pass-an- массив-строк-как-параметра-функции-в-с
stackoverflow: как-работает-массив-указателей-указателей-указателей
stackoverflow: whats-your-favourite-programmer-ignorance-pet-peeve
drexel.edu: массивы символов
Многие из них включают обсуждение массивов, но я не хочу этого делать.
Я пишу пример программы, чтобы научиться передавать char *
и char **
в C. Это упражнение по передаче char * без использования (указателей на) массивов. Также не стоит беспокоиться об эффективности исполнения. :-)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void get_args_works(int, char **, char **);
void get_args_broken(int, char **, char *);
char *get_string(int, char **);
int main(int argc, char **argv)
{
char *string_works;
char *string_broken;
get_args_works(argc, argv, &string_works);
get_args_broken(argc, argv, string_broken);
printf("in main string_works (%p) = %s\n",string_works,string_works);
free(string_works);
printf("in main string_broken (%p) = %s\n",string_broken,string_broken);
free(string_broken);
}
void get_args_works(int argc, char **argv, char **string)
{
*string = get_string(argc, argv);
printf("in get_args_works %p string %s\n",*string,*string);
}
void get_args_broken(int argc, char **argv, char *string)
{
string = get_string(argc, argv);
printf("in get_args_broken %p string %s\n",string,string);
}
char * get_string(int argc, char **argv)
{
int i;
char *string;
string = malloc(40);
// placeholder in case -s switch not found below
strcpy(string,"-s switch not found below");
for(i = 0; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch(argv[i][1])
{
case 's':
// release above malloc(40) for "-s switch not found below"
free(string);
// make room for storing variable
string = malloc(strlen(argv[++i]) + 1);
// the argv just after -s
strcpy (string,argv[i]);
break;
}
}
}
return string;
}
Вы также можете просмотреть тот же код на github.
Приведенный выше код в некоторой степени самодокументируется. main()
объявляет две переменные типа char * и передает их в качестве параметров соответствующим get_args()
функциям.
Каждая функция get_args()
вызывает char * get_string(int, char **)
, используя один и тот же вызов (но по-разному собирать возвращаемое значение).
get_string()
отлично работает; он выполняет malloc()
и возвращает указатель обратно на вызывающую функцию. Этот код работает, и каждая get_args()
функция получает возвращаемое значение, как я и ожидал.
Но затем, когда функции get_args () возвращаются к main()
, почему значение разыменованного указателя возвращается к main (из get_args_works()
, но не к значению указателя (из get_args_broken()
)?
(т.е. я вижу, что если я разыменую указатель (&string_works
) при отправке в качестве параметра, он работает. Но почему? Разве char * string_broken
уже не указатель? Зачем ему нужно "дополнительное" разыменование при отправке в качестве параметра?)
Я надеюсь на выигрышный ответ, который объяснит, как вы (да, вы) концептуализируете отправку char * в качестве параметра, а не получение его в качестве возвращаемого значения функции.