2016-04-06 3 views
0

(Proficient at C++, новичок в C) получает ошибку segfault из вызова addArray() в main(). Я проверил множество сообщений и несколько текстов, он компилируется, но не повезло. Я кодирую его на VS2015, и все обычные удобные подсказки есть с указателями и т. Д. Очистите что-то, что я не знаю или синтаксическая ошибка. Это дистиллированный код, который воспроизводит ошибку.Добавление элемента массива в массив в структуре

#include<stdio.h> 
#include <stdlib.h> 
#define TYPE int 

struct arrayHolder { 
    TYPE data[100]; 
    int count; 
}; 

//prototypes. 
void initArray(struct arrayHolder *); 
void addArray(struct arrayHolder *, TYPE); 


int main() { 
    struct arrayHolder * myStruct = NULL; 
    initArray(myStruct); 
    addArray(myStruct, 123); 
} 

/* Allocate memory for struct arrayHolder */ 
void initArray(struct arrayHolder * b) { 
    b = (struct arrayHolder *)malloc(sizeof(struct arrayHolder)); 
    b->count = 0; 
} 


/* Add an element to data[] */ 
void addArray(struct arrayHolder * b, TYPE v) { 
    int count = b->count; 
    b->data[count] = v; 
    (b->count)++; 
} 
+2

аргументы передаются по значению. Назначение внутри initArray() не имеет эффекта вне функции. –

+0

@ def1: Но не передаю ли указатель? – Chris

+0

@ Chris: Да, и вы можете изменить данные, на которые указывает указатель, но вы назначаете новое значение самому указателю, который не будет переноситься вне функции, используйте указатель на указатель. – Unimportant

ответ

2

Как заметил @ def1, вы передаете указатели по значению. Это не проблема для addArray() - проблема с initArray(). Параметр этой функции является локальным для функции, поэтому, когда вы назначаете указатель malloc() ed, результат не отображается в main(). В конечном итоге вы передаете NULL указатель на addArray().

Существует не менее двух возможных решений.

  1. В коде, представленном, это мне не ясно, почему struct arrayholder должен быть динамически распределяемой на всех. Если в main() вы заявляете вместо struct arrayholder myStruct; и удаляете malloc() звонок от initArray(), тогда все остальное должно работать как есть.

  2. В качестве альтернативы, если вам необходимо выполнить динамическое распределение, либо вы должны вернуть указатель на выделенную память от initArray() (в этом случае эта функция не требует параметра), либо вам нужно передать двойной указатель на функция, так что указатель main() может быть обновлен.

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

int main() { 
    struct arrayHolder * myStruct = NULL; 
    initArray(&myStruct);     /* difference here */ 
    addArray(myStruct, 123); 
} 

/* Allocate memory for struct arrayHolder */ 
void initArray(struct arrayHolder ** b) { 
    /* no cast is required here in C, and many account one poor style: */: 
    *b = malloc(sizeof(struct arrayHolder)); 
    (*b)->count = 0; 
} 
+0

спасибо !! Это отличается от C++ ... – Chris

+0

@ Крис, я рад помочь. Однако, как заметил Олаф, ваш код был неверен и на C++. Все мои комментарии применимы и там, за исключением удаления значения возвращаемого значения 'malloc()'. C++ требует, чтобы он выполнялся. –

+0

@ Крис: Это не отличается от пропущенных указателей на C++. У вас есть возможность использовать ссылку на указатель, но это другой тип и имеет отличный синтаксис. – Olaf

1
void initArray(struct arrayHolder * b) 

Здесь вы передаете указатель на структуру arrayHolder к функции. Указатель передается по значению, что означает, что это копия. Вы можете изменить данные, на которые указывает указатель, но когда вы назначаете результат malloc на b, вы изменяете копию самого указателя, которая не будет влиять на указатель в main.

Возможное решение - использовать указатель на указатель.

void initArray(struct arrayHolder ** b) { 
    *b = (struct arrayHolder *)malloc(sizeof(struct arrayHolder)); 
    (*b)->count = 0; 
} 
Смежные вопросы