LINUX.ORG.RU
Ответ на: комментарий от qulinxao

дык ты бредом назвал передачу массива по значению

Так ведь бред и есть.

Тому шта это типичный случай, когда вместо вопроса «у меня вот такая задача, как её решить?», задают вопрос «я придумал идиотский способ решения, как его реализовать?»

anonymous
()
Ответ на: комментарий от qulinxao

Нет. Стек изменяется, поэтому положение элемента всё равно придётся вычислять.

У тебя двойная работа:

1) вычисление адреса элемента для копирование в стек (ptr + index);

2) вычисление адреса элемента в стеке (SP - index - <смещение>).

ziemin ★★
()
Ответ на: комментарий от qulinxao

зависит от железки да?

Назови современную железку, в которой обращение к локальному фрейму идёт не через указатель.

anonymous
()
Ответ на: комментарий от qulinxao
void hrenoten(uint8_t *ptr, size_t L){
  uint8_t *copy = calloc(L, 1);
  memcpy(copy, ptr, L);
  // so whatever you want with data in array _copy_
}

int main(int A, char **C){
  // size_t L;
  // uint8_t *ARR = calloc(L, 1);
  // fill array ARR with size L
  // and now call funtion  
  hrenoten(ARR, L);
}
Eddy_Em ☆☆☆☆☆
()
Ответ на: Ни как. от qulinxao

Ник то же не мешает сделать так:

int a[SIZE];
for(int i = 0; i < SIZE; i++) { a[i] = arg_array[i]; }
Всего две строчки.

Deleted
()
Ответ на: комментарий от ziemin

ну что не понятного то?

язык(реализация) может вообще апаратного стека.

речь про вызов с аргументом по значению.

qulinxao ★★☆
() автор топика
Ответ на: комментарий от Deleted

это на стороне вызывающего(предзагрузка) или на стороне функции?

ну и SIZE -прекомпилированая контстанта у тя так?

qulinxao ★★☆
() автор топика
Ответ на: комментарий от qulinxao

может вообще апаратного стека.

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

ziemin ★★
()
Ответ на: комментарий от qulinxao

это на стороне вызывающего(предзагрузка) или на стороне функции?

На стороне функции.

ну и SIZE -прекомпилированая контстанта у тя так?

Современный стандарт Си позволяет выделять на стеке массивы произвольной длины. Так что можешь передать размер параметром.

anonymous
()
Ответ на: комментарий от ziemin

сорри .

может вообще апаратного стека нет.

оки, может нам важно иметь доступ из функции к массиву на момент вызова , а не на момент выполнения ( вдруг он volitile али ещё чё)

qulinxao ★★☆
() автор топика
Ответ на: комментарий от anonymous

как в С передать массив по значению в функцию?

и уже вообщет подсказали - путём оборачивания в структуру - т.е синтаксическое преодоление, остальное в треде обсуждение с фанатиками.

qulinxao ★★☆
() автор топика
Ответ на: комментарий от qulinxao

оки, может нам важно иметь доступ из функции к массиву на момент вызова , а не на момент выполнения

Капец, как тебя сложно понять. Ты так и не научился писать по-русски?

Но вообще-то... об этом должна думать вызывающая сторона. Если она хочет менять данные, например, в другом потоке, пусть создаёт копию. Это не проблема вызываемой функции.

anonymous
()
Ответ на: комментарий от qulinxao

код примера?

void f(size_t n, int * _arr)
{
    int arr[n];

    for (size_t i = 0; i < n; i++)
        arr[i] = _arr[i];

    /* bla
       bla
       bla */
}
anonymous
()

Когда qulinxao доучит русский язык?

Когда qulinxao доучит русский язык?

[упоротые]

aedeph_ ★★
()
Ответ на: комментарий от qulinxao

оки, может нам важно иметь доступ из функции к массиву на момент вызова , а не на момент выполнения

Так у тебя конкретное условие или ты теоретизируешь? Многопоточное приложение что ли? И второй поток непредсказуемо меняет элементы массива? А как ты можешь быть уверен, что он не успеет их поменять ДО вызова твоей функции?

( вдруг он volitile али ещё чё)

А ты точно знаешь, что это такое?

ziemin ★★
()
Ответ на: комментарий от anonymous

зачем? если можно синтаксически сказать компилятору вместе вызова сделать всю машинерию.

т.е идея со стуктурой с единственным полем массив неизвестного размера . - т.е по сути «тип» неизвестной длины байт значение которого автоматом компилятор генерирует код копирования на стек - очень и очень в тему.

qulinxao ★★☆
() автор топика
Ответ на: комментарий от ziemin

ну слу .

исходно вопрос как получить массив по значению в функцию.

большинство предложивших решение(приемлимое - оборачивание в структуру тогда компилятор сам всё чё нужно соотворит) анонимы :)

большинство изначально отрицавших возможность , дополнили своё резюме ненужностю и «оторваностью от жизни»

qulinxao ★★☆
() автор топика
Ответ на: комментарий от qulinxao

если можно синтаксически сказать компилятору вместе вызова сделать всю машинерию.

Затем, что если у тебя многопоточка, тебе понадобится синхронизация. Компилятор за тебя мутексы не расставит.

т.е идея со стуктурой с единственным полем массив неизвестного размера . - т.е по сути «тип» неизвестной длины байт значение которого автоматом компилятор генерирует код копирования на стек - очень и очень в тему.

Не в тему, потому что не заработает. В Си (в большинстве языков, если не во всех) у всех by-value значений должен быть известен размер во время компиляции.

Ты можешь затолкать в стек что-то типа struc {int arr[CONST];}, но никакой «переменной длины» ты так не затолкаешь.

anonymous
()
Ответ на: комментарий от qulinxao

т.е по сути «тип» неизвестной длины байт значение которого автоматом компилятор генерирует код копирования на стек - очень и очень в тему.

Длина должна быть известна. И в этом случае компилятор сгенерирует инструкции копирования и для присваивания структур, так что лучше всё-таки передавать указатель на копию структуры.

Видел я одного товарисча, который на железке с 255 байтами стека лепил локальный массив на 255 байт. Очень он удивлялся работе программы.

ziemin ★★
()
cat 1.c
#include <stdio.h>

typedef struct{
  char arr[20];
} arr_20;

void proceed(arr_20 X){
  int i;
  for(i = 0; i < 20; i++)
    printf("arr[%02d] = %c\n", i, X.arr[i]);
}

int main(int a, char **c){
  arr_20 X;
  int i;
  for(i = 0; i < 20; i++)
    X.arr[i] = 'a' + i;
  proceed(X);
}

gcc -S 1.c

cat 1.s
	.file	"1.c"
	.section	.rodata
.LC0:
	.string	"arr[%02d] = %c\n"
	.text
	.globl	proceed
	.type	proceed, @function
proceed:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movl	$0, -4(%rbp)
	jmp	.L2
.L3:
	movl	-4(%rbp), %eax
	cltq
	movzbl	16(%rbp,%rax), %eax
	movsbl	%al, %edx
	movl	-4(%rbp), %eax
	movl	%eax, %esi
	movl	$.LC0, %edi
	movl	$0, %eax
	call	printf
	addl	$1, -4(%rbp)
.L2:
	cmpl	$19, -4(%rbp)
	jle	.L3
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	proceed, .-proceed
	.globl	main
	.type	main, @function
main:
.LFB1:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$80, %rsp
	movl	%edi, -36(%rbp)
	movq	%rsi, -48(%rbp)
	movl	$0, -4(%rbp)
	jmp	.L5
.L6:
	movl	-4(%rbp), %eax
	addl	$97, %eax
	movl	%eax, %edx
	movl	-4(%rbp), %eax
	cltq
	movb	%dl, -32(%rbp,%rax)
	addl	$1, -4(%rbp)
.L5:
	cmpl	$19, -4(%rbp)
	jle	.L6
	movq	-32(%rbp), %rax
	movq	%rax, (%rsp)
	movq	-24(%rbp), %rax
	movq	%rax, 8(%rsp)
	movl	-16(%rbp), %eax
	movl	%eax, 16(%rsp)
	call	proceed
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1:
	.size	main, .-main
	.ident	"GCC: (GNU) 4.7.2"
	.section	.note.GNU-stack,"",@progbits

И смысл?

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от ziemin

Видел я одного товарисча, который на железке с 255 байтами стека лепил локальный массив на 255 байт. Очень он удивлялся работе программы.

А как такой товарищ вообще попал на такую работу?

anonymous
()
Ответ на: комментарий от anonymous

У нас в стране — в порядке вещей, когда люди вынуждены выполнять работу, в которой совершенно некомпетентны.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от qulinxao

что сложно представить ситуацию в которой копирование на стек при вызове экономичней чем каждократное разыминование?

да, сложно. Если ты про массив.

Неужели непонятно, что ты(компилятор) всё равно будешь разименовывать перед копированием? Массив-то у тебя в ДРУГОЙ части стека лежит, не в том фрейме, в которой ты функцию вызываешь.

А структура в данном случае == костыль.

emulek
()
Ответ на: комментарий от anonymous

Ты можешь затолкать в стек что-то типа struc {int arr[CONST];}, но никакой «переменной длины» ты так не затолкаешь.

теоретически это возможно в PureC (в своём варианте PureC конечно, ибо в апстрим никто такую багофичу не воткнёт).

emulek
()
Ответ на: комментарий от qulinxao

это на стороне вызывающего(предзагрузка) или на стороне функции?

Я бы так сделал, скорее всего. Но если размеры массива фиксированы - то malloc нафиг не нужен.

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

int my_func_with_array(int original_array[], int size) {
    int *copy_of_array;
    copy_of_array = malloc(sizeof(int) * size);
    for(int i = 0; i < size; i++)
        copy_of_array[i] = original_array[i];
    // твой код, работающий с массивом-копией copy_of_array
    // ...
    // после всех манипуляций с массивом
    free(copy_of_array);
}

int main (int argc, char *argv[]) {
    int my_arrray[] = {1, 2, 3, 4, 5};
    my_func_with_array(my_arrray, 5);
}
П.С. для С99. Если юзаешь более старую, объявление переменной i вынеси из цикла.

Deleted
()
Последнее исправление: Bizun (всего исправлений: 1)
Ответ на: комментарий от anonymous

однако варарг позволяет переменное число(константное в месте вызова , но переменое в разных местах вызова одной и той же функции).

т.е в месте вызова мы можем приводить к разным struct {int arr[CONSTНужное в этом месте];} , а функция будет тем или иным способом полученый массив использовать.

походу набор struct {int arr[CONSTНужное в этом месте]}; подходящий вариант (может , стоит понять как варарг-магию)

qulinxao ★★☆
() автор топика
Ответ на: комментарий от qulinxao

однако варарг позволяет переменное число(константное в месте вызова , но переменое в разных местах вызова одной и той же функции).

т.е в месте вызова мы можем приводить к разным struct {int arr[CONSTНужное в этом месте];} , а функция будет тем или иным способом полученый массив использовать.

Редкостное извращение. Но возразить нечего, работать будет.

Но ты так и не смог объяснить, зачем тебе это извращение нужно.

anonymous
()
Ответ на: комментарий от qulinxao
#define ccpy(arg) ({\
  memcpy((typeof(*arg)[sizeof(arg)/sizeof(*arg)]){0}, arg, sizeof(arg));\
})

void f(int m[10]) {
  fprintf(stderr, "%p\n", &m[1]);  
}
#define f(arg) f(ccpy(arg));

int32_t main(void) {
  int m[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  fprintf(stderr, "%p\n", &m[1]);
  f(m);
}

И да, это не нужно. Никто, чей скилл чуть выше днища не юзает говномассивы.

Если мне надо передать то, что я написал выше в функцию - я напишут максимум так:

f((int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
И даже это не нужно.

И да, мне смешно смотреть на с89 нулей выше по треду.

anonymous
()

Не извращайся.

Передавай указатель на массив + его размер. А внутри уже делай выборку элементов и делай сними что хочешь.

Dron ★★★★★
()
Ответ на: комментарий от anonymous

Ну там выше много предложений типа моих, только в с89-стиле уровня студента 1го курса. Вот мне и смешно как мацаны дёргают маллоки, алоки и прочее.

anonymous
()
Ответ на: комментарий от Dron

лишнее постоянное разименнование - т.е есть ситуация когда передача по значению действительно нужна.

qulinxao ★★☆
() автор топика
Ответ на: комментарий от qulinxao

лишнее постоянное разименнование - т.е есть ситуация когда передача по значению действительно нужна.

Ты совсем глупый? Тебе уже 100500 объяснили, что в машкоде никакой значимой разницы не будет.

anonymous
()
Ответ на: комментарий от qulinxao

Ах да, забыл, у вас же ещё и sizeof() должен корректно работать. Как сложна жизнь нулей - ну костыляй через структуры, len"ы и прочее.

По пацаночке это едлается через структуры вида {type * begin, * end}, либо {type * begin; size_t len;} и никаких проблем не создаётся.

anonymous
()
Ответ на: комментарий от anonymous

лучше пониманить границы языка(т.е, что возможно сделать средствами самого языка(в переносимой части желательно))

а вот мракобесное «вси массивы это указатель, анафема кто иначе» внушает уважение нашей системе образования.

qulinxao ★★☆
() автор топика
Ответ на: комментарий от x0r

Не, через varargs, лучше не стоит, как раз недавно, на практике, узнал, что не во всех реализациях эта фишка срабатывает:)

batbko
()
Ответ на: комментарий от anonymous

дык какая разница , ты ведь про слайсы рекёш.

в исходной нужно массив по значению.

qulinxao ★★☆
() автор топика
Ответ на: комментарий от qulinxao

Нету, единственное реальное отличие «по-значениею» - это копирование - всё. Копирование делается через копирование, а копия передаётся, либо делается уже в функции. vec(array)_t mdup() - запили и делай, как делал я выше. f(mdup(m));

typedef struct {
  int * begin; uint32_t len;
} vec_t;

#define mdup(arg) ({\
  (vec_t){memcpy((typeof(*arg)[sizeof(arg)/sizeof(*arg)]){0}, arg, sizeof(arg)), sizeof(arg)/sizeof(*arg)};\
})


void f(vec_t v) {
  fprintf(stderr, "%p\n", sizeof(v.begin));
  int * it = v.begin;
  do {
    fprintf(stdout, "%d ", *it);
  } while(++it != (v.begin + v.len));
  fprintf(stdout, "\n");
}
// #define f(arg) f(mdup(arg));

int32_t main(void) {
  int m[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  f(mdup(m));
}

Вся твоя мура и бредни с разименованием вызвана лишь твоей анскильностью.

anonymous
()
Ответ на: комментарий от anonymous

sizeof(v.begin) - это опечатка, вернее кривая копипаста после попытки запилить для вас даже sizeof() для vec_t, но мне стало лень.

anonymous
()
Ответ на: комментарий от qulinxao

слу. ты ведь про то как циклы профилят в курсе?

По-русски пиши, ё-моё.

anonymous
()
Ответ на: комментарий от qulinxao

Скопируй локально, через int copy[ n] + memcpy и передай, если надо именно копию, но структуру не хочешь объявлять. Что за платформа, в которой индексирование на стеке не то же, что от базы в любом другом месте, если не секрет?

arturpub ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.