Как мне скопировать значение, а не адрес указателя в C здесь? - PullRequest
0 голосов
/ 02 мая 2020

Я хочу, чтобы значение names[j] было введено в name в функции diddle(). Я попробовал пару вещей, и либо значение в name отражает изменение с name[j] на "0", когда я его возвращаю, либо я получаю segfault. Что мне не хватает?

randomGenerator возвращает целое число, соответствующее индексу names[].

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

char* names[9];

//char* diddle(char *names[]) {
void diddle(char *names[], char *name) {
    int i;

    while (1) {

        int j = randomGenerator(0,9);
        printf("j is %d\n",j);
        int x;
        x = strcmp(names[j],"0");
        printf("names[j] is %s and x is %d\n",names[j],x);
        if (x != 0) {
            strcpy(name,names[j]);
            strcpy(names[j],"0");
            break;
        }

    }
    //return name;
}


int main() {

    names[0] =  (char *) malloc(4 * sizeof(char*));
    strcpy(names[0],"foo");

    names[1] =  (char *) malloc(4 * sizeof(char*));
    strcpy(names[1],"bar");

    names[2] =  (char *) malloc(4 * sizeof(char*));
    strcpy(names[2],"baz");

    names[3] =  (char *) malloc(4 * sizeof(char*));
    strcpy(names[3],"qux");

    names[4] =  (char *) malloc(4 * sizeof(char*));
    strcpy(names[4],"zed");

    names[5] =  (char *) malloc(4 * sizeof(char*));
    strcpy(names[5],"pug");

    names[6] =  (char *) malloc(4 * sizeof(char*));
    strcpy(names[6],"unk");

    names[7] =  (char *) malloc(4 * sizeof(char*));
    strcpy(names[7],"fed");

    names[8] =  (char *) malloc(4 * sizeof(char*));
    strcpy(names[8],"hip");

    names[9] =  (char *) malloc(4 * sizeof(char*));
    strcpy(names[9],"gib");

    int i;
    for(i = 0; i < 7; i++) {
        //char *name = diddle(&names[0]);
        char *name = NULL;
        diddle(&names[0],&name);

        printf("main loop: name is %s\n", name);
    }

    for (i = 0; i < 10; i++) {
        free(names[i]);
    }       
}

1 Ответ

1 голос
/ 02 мая 2020

Если у вас есть массив, объявленный как

char* names[9];

, то допустимый диапазон индексов для этого массива составляет [0, 9).

Так что эти операторы

names[9] =  (char *) malloc(4 * sizeof(char*));
strcpy(names[9],"gib");

получить доступ к несуществующему элементу массива с неверным индексом 9.

Этот l oop

for (i = 0; i < 10; i++) {
    free(names[i]);
} 

также неверен по той же причине.

Не используйте маги c числа, такие как 9 0r 10. Используйте именованные константы как например

enum { N = 9 };
char* names[N];

//...

for (i = 0; i < N; i++) {
    free(names[i]);
} 

И нет смысла объявлять массив names как глобальную переменную. Вы можете объявить это в main.

Хотя выделенная память

names[0] =  (char *) malloc(4 * sizeof(char*));

может вместить строку из четырех символов

strcpy(names[0],"foo");

, тем не менее, такое распределение только смущает читателей код. Вместо этого напишите в этом другом аналогичном выражении

names[0] =  (char *) malloc(4 * sizeof(char));
                                       ^^^^^

или просто

names[0] =  (char *) malloc( 4 );

Th функцию diddle второй параметр имеет тип char *

void diddle(char *names[], char *name) {

но в вызове функции

diddle(&names[0],&name);

используется выражение &name типа char **.

В результате этого оператора

strcpy(name,names[j]);

вызывает неопределенное поведение. Даже если переданное выражение имеет правильный тип

diddle(&names[0],&name);

, тем не менее функция снова имеет неопределенное поведение, поскольку переданный указатель является нулевым указателем. Поэтому вы не можете использовать strcpy с нулевым указателем.

Вместо нулевого указателя

char *name = NULL;

вы можете использовать массив символов, например

char name[4];
...