C указатели пересмотрены - PullRequest
7 голосов
/ 25 ноября 2011

Я учусь использовать указатели.
У меня есть несколько вопросов по поводу кода упражнения, который я написал.

Во-первых, если у меня есть следующий код функции:

//function prototype
void processCars(char *, char []);

int main(){
...
//actual callto the function
processCars(strModel[x], answer);
...
}

void processCars(char * string1, char string2[])
{
...
}

КакБыло бы правильно определить аргументы этой функции processCars?Первый - char * - это указатель на char, который является начальным местоположением строки (или, лучше, массива символов)?Второй фактически является массивом символов напрямую.

Теперь, предположим, я хочу передать по ссылке несколько массивов строк и даже массив структур.Мне удалось создать следующий код, который работает, но я все еще не до конца понимаю, что делаю.

typedef struct car {

    char make[10];
    char model[10];
    int year;
    int miles;

} aCar; // end type

// function prototype
void processCars( aCar * , char **, char **, int *, int *);

//aCar * - a pointer to struct of type car 
//char **, char ** 
// int * - a pointer to integer
//  Arrays passed as arguments are passed by reference.
// so this prototype works to
//void processCars( aCar * , char **, char **, int [], int []);


int main(){

    aCar myCars[3]; // an array of 3 cars

    char *strMakes[3]={"VW","Porsche","Audi"}; // array of 3 pointers?
    char *strModel[3]={"Golf GTI","Carrera","TT"};
    int intYears[3]={2009,2008,2010};
    int intMilage[3]={8889,24367,5982};

    // processCars(myCars, strMakes);
    processCars(myCars, strMakes, strModel, intYears, intMilage);

return 0;
} // end main

//  char ** strMakes is a pointer to array of pointers ?
void processCars( aCar * myCars, char ** strMakes, \
                  char ** strModel, int * intYears, \
                  int * intMilage ){
}

Итак, моя проблема в том, как определить это "char ** strMakes".Что это, почему это работает для меня?

Я также заметил, что не могу изменить часть строки, потому что, если я исправляю (или ссылки, которые я читаю), строки доступны только для чтения.Так что, как и в python, я могу использовать индексы массива для доступа к букве V:

printf("\n%c",strMakes[0][0]); 

Но, в отличие от Python, я не могу ее изменить:

strMakes[0][0]="G" // will not work? or is there a way I could not think of?

Итак,спасибо за чтение моего длинного поста и многих вопросов о указателях и c-строках.Ваши ответы приветствуются.

1 Ответ

6 голосов
/ 25 ноября 2011

Внутри самой функции оба аргумента будут указателями . [] в списке параметров не имеет абсолютно никакого значения, это просто синтаксический сахар.

Хотя между массивом и указателем существует явная разница, переданный массив функции всегда распадается на указатель соответствующего типа. Например, массив типа char[3] будет уменьшаться до char *, char *[3] будет уменьшаться до char **.

char *strMakes[3] - это массив длиной 3, который содержит указатели на строки, хранящиеся где-то еще, вероятно, в области процесса, доступной только для чтения. Попытка изменить сами строки приведет к неопределенному поведению, скорее всего, к ошибке защиты.

Если вы хотите иметь возможность изменять строки, вы можете объявить его как массив, содержащий массивы , а не указатели:

char strMakes[3][20] = {"VW", "Porsche", "Audi"};

Таким образом, строки будут храниться последовательно в пределах внешнего массива.

Еще один способ - сохранить массив указателей, но указатели должны указывать на изменяемую память:

/* these strings are mutable as long as you don't write past their end */
char str1[] = "VW";
char str2[] = "Porsche";
char str3[] = "Audi";
char *strMakes[3] = {str1, str2, str3};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...