Я прочитал несколько обсуждений прохождения char * в C.
stackoverflow: передача массива строк в качестве параметра в функцию в c
stackoverflow: как работает массив массивов указателей на указатели
stackoverflow: что-твой-любимый-программист-невежество-любимчик-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()
, почему значение разыменованного указателя возвращается к основному (с get_args_works()
, но не к значению указателя (с get_args_broken()
)?
(то есть я вижу, что если я разыменую указатель (&string_works
) при отправке в качестве параметра, он работает. Но почему? Разве char * string_broken
уже не указатель? Зачем нужна "дополнительная" разыменование при отправке в качестве параметра?)
Я надеюсь на выигрышный ответ, который объясняет, как вы (да, вы) концептуализируете отправку char * в качестве параметра против получения его в качестве возвращаемого значения функции.