Я относительно новичок в C, и мне нужна помощь с методами работы с массивами. Исходя из Java-программирования, я привык говорить int [] method()
, чтобы возвращать массив. Тем не менее, я обнаружил, что с C вы должны использовать указатели для массивов, когда вы возвращаете их. Будучи новым программистом, я действительно не понимаю этого вообще, даже с многочисленными форумами, которые я просматривал.
По сути, я пытаюсь написать метод, который возвращает массив символов в C. Я предоставлю метод (давайте назовем его returnArray) с массивом. Он создаст новый массив из предыдущего массива и вернет на него указатель. Мне просто нужна помощь о том, как начать и как прочитать указатель, как только он будет отправлен из массива. Любая помощь, объясняющая это, приветствуется.
Предлагаемый формат кода для функции возврата массива
char *returnArray(char array []){
char returned [10];
//methods to pull values from array, interpret them, and then create new array
return &(returned[0]); //is this correct?
}
Абонент функции
int main(){
int i=0;
char array []={1,0,0,0,0,1,1};
char arrayCount=0;
char* returnedArray = returnArray(&arrayCount); ///is this correct?
for (i=0; i<10;i++)
printf(%d, ",", returnedArray[i]); //is this correctly formatted?
}
Я еще не проверял это, так как мой компилятор C в данный момент не работает, но я хотел бы выяснить это
Ответы:
Вы не можете вернуть массивы из функций в C. Вы также не можете (не должны) делать это:
returned
создается с автоматической продолжительностью хранения, и ссылки на него становятся недействительными, как только он покидает объявленную область, т. е. когда функция возвращается.Вам нужно будет динамически распределять память внутри функции или заполнять предварительно выделенный буфер, предоставленный вызывающей стороной.
Опция 1:
динамически распределять память внутри функции (вызывающая сторона отвечает за освобождение
ret
)Назовите это так:
Вариант 2:
заполнить предварительно выделенный буфер, предоставленный вызывающей стороной (вызывающая сторона выделяет
buf
и передает функции)И назовите это так:
источник
Обработка массивов в С сильно отличается от обработки в Java, и вам придется соответствующим образом изменить свое мышление. Массивы в C не являются объектами первого класса (то есть выражение массива не сохраняет свою «массивность» в большинстве контекстов). В Си выражение типа «массив N-элементов
T
» будет неявно преобразовано («распад») в выражение типа «указатель наT
», за исключением случаев, когда выражение массива является операндомsizeof
или унарных&
операторов, или если Выражение массива - это строковый литерал, используемый для инициализации другого массива в объявлении.Среди прочего, это означает, что вы не можете передать выражение массива функции и получить его как тип массива ; функция фактически получает тип указателя:
При вызове
foo
выражениеstr
преобразуется из типаchar [6]
вchar *
, поэтому вместо параметраfoo
объявляется первый параметр . Так как выражение массива является операндом оператора, оно не преобразуется в тип указателя, поэтому вы получаете количество байтов в массиве (6).char *a
char a[6]
sizeof str
sizeof
Если вам действительно интересно, вы можете прочитать « Развитие языка Си» Денниса Ричи, чтобы понять, откуда это лечение.
В результате функции не могут возвращать типы массивов, что нормально, поскольку выражения массива также не могут быть целью назначения.
Самый безопасный метод для вызывающего - определить массив и передать его адрес и размер функции, которая должна записать в него:
Другой метод заключается в том, что функция динамически выделяет массив и возвращает указатель и размер:
В этом случае вызывающая сторона отвечает за освобождение массива с помощью
free
функции библиотеки.Обратите внимание, что
dst
в приведенном выше коде это простой указатель наchar
, а не указатель на массивchar
. Указатель C и семантика массива таковы, что вы можете применить оператор индекса[]
к выражению типа массива или типа указателя; обаsrc[i]
иdst[i]
получат доступ кi
'-ому элементу массива (даже еслиsrc
имеет только тип массива).Вы можете объявить указатель на массив из N элементов
T
и сделать нечто подобное:Несколько недостатков с вышесказанным. Прежде всего, более старые версии C ожидают
SOME_SIZE
быть константой времени компиляции, то есть функция будет работать только с одним размером массива. Во-вторых, вы должны разыменовать указатель перед применением индекса, который загромождает код. Указатели на массивы работают лучше, когда вы имеете дело с многомерными массивами.источник
bar
указатель, а не массив. В контексте объявления параметров функции,T a[N]
иT a[]
оба рассматриваются какT *a
.void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
последний параметр должен иметьsize_t
тип notchar
.Я не говорю, что это лучшее или предпочтительное решение данной проблемы. Однако может быть полезно помнить, что функции могут возвращать структуры. Хотя функции не могут возвращать массивы, массивы могут быть обернуты в структуры, и функция может возвращать структуру, тем самым перенося массив с собой. Это работает для массивов фиксированной длины.
Я приглашаю комментировать сильные и слабые стороны этой техники. Я не удосужился сделать это.
источник
CHAR_ARRAY returned
кучи? Это, конечно, не может в стеке (в кадре стекаreturnArray()
правильно?Как насчет этого ужасно злого внедрения?
array.h
main.c
источник
struct
в качестве контейнера / объекта массива. Думайте об этом как о C ++ std :: vector. Препроцессор расширил быint
версию этого доstruct intArray { int* contents; int size; };
.В вашем случае вы создаете массив в стеке, и как только вы покидаете область действия функции, массив будет освобожден. Вместо этого создайте динамически размещенный массив и верните на него указатель.
источник
new
Си нет оператора. Это C ++.sizeof(char)
гарантированно будет1
, так что в этом случае вы можете отказаться от этогоmalloc
.&arr
. Вы хотитеarr
бытьchar *
, и передать это в использованииarr
.Вы можете сделать это, используя кучную память (посредством вызова malloc () ), как и другие ответы, представленные здесь, но вы всегда должны управлять памятью (используйте функцию free () каждый раз, когда вы вызываете свою функцию). Вы также можете сделать это со статическим массивом:
Вы можете использовать его, не беспокоясь об управлении памятью.
В этом примере вы должны использовать статическое ключевое слово в определении массива, чтобы установить на время приложения время жизни массива, чтобы оно не уничтожалось после оператора return. Конечно, таким образом вы занимаете SIZE байтов в своей памяти на весь срок службы приложения, так что измеряйте его правильно!
источник
Ваш метод вернет локальную переменную стека, которая потерпит неудачу. Чтобы вернуть массив, создайте его вне функции, передайте его по адресу в функцию, затем измените его или создайте массив в куче и верните эту переменную. Оба будут работать, но первый не требует динамического выделения памяти для правильной работы.
источник
Вы можете использовать код как это:
Когда вы это сделаете, память должна быть позже освобождена, передав адрес свободным.
Есть и другие варианты. Подпрограмма может вернуть указатель на массив (или часть массива), который является частью некоторой существующей структуры. Вызывающая сторона может передать массив, а процедура просто записывает в массив, а не выделяет место для нового массива.
источник