LINUX.ORG.RU

Структуры - передача оных в функцию и обратно.

 , ,


0

2

Доброго времени суток! Страшно извиняюсь, но не смог подобрать под нижеописанное верный запрос в поисковиках...

#include <stdio.h> 

typedef struct newfile{
	 int *set1, *test;
} Settings;

void testing(Settings *Set){
	Set->set1 = 1;
	Set->test = 3;
};

void main(void){
	Settings *mystr;
	testing(mystr); // &mystr, mystr
	printf("%d, %d\n", mystr->set1, mystr->test);
}

Как видно из кода - хочу в функцию передать структуру, забить в нее данные и вернуть без мусора. Однако, либо сегфолт, либо не компилится. Этот вариант нагляден, но не работает, хоть и собирается. Подскажите пожалуйста, как разрулить видимости. Спасибо, товарищи!

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 1)

Кто будет память выделять под структуру?

#include <stdlib.h> 

void main(void){
	Settings *mystr = (Settings*) malloc(sizeof(Settings));
	testing(mystr); // &mystr, mystr
	printf("%d, %d\n", mystr->set1, mystr->test);
}
kostik1
()

не 1 и 3, а malloc и malloc, а потом уже 1 и 3 ну и как уже заметили

Кто будет память выделять под структуру?

metawishmaster ★★★★★
()
Последнее исправление: metawishmaster (всего исправлений: 1)
#include <stdio.h> 

typedef struct newfile{
	 int set1, test;
} Settings;

void testing(Settings *Set){
	Set->set1 = 1;
	Set->test = 3;
};

void main(void){
	Settings mystr;
	testing(&mystr);
	printf("%d, %d\n", mystr.set1, mystr.test);
}

joy4eg ★★★★★
()
#include <stdio.h>
#include <stdlib.h>         /* malloc */

typedef struct newfile{
	 int set1, test;    /* тут поинтеры лишние, или их тоже надо будет malloc'ить */
} Settings;

void
testing(Settings *Set)
{
	Set->set1 = 1;
	Set->test = 3;
};

/* main возвращает int! */
int
main()
{
	Settings *mystr1, mystr2;

	mystr1 = malloc(sizeof(Settings));   /* cast лишний! */
        if (!mystr1)
                return -1;  /* проверять значения тоже надо */

	testing(mystr1);    /* вариант один */
	testing(&mystr2);   /* вариант два */
        
	printf("%d, %d\n", mystr1->set1, mystr1->test);
	printf("%d, %d\n", mystr2.set1, mystr2.test);

        free(mystr1);       /* не забываем подтираться :) */

	return 0;
}
beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 5)
Ответ на: комментарий от joy4eg

Удваиваю этот способ. Malloc без причины - признак альтернативности мышления.

schizoid ★★★
()
Ответ на: комментарий от joy4eg
#include <stdio.h> 

typedef struct newfile{
	 int set1, test;
} Settings;

inline void testing(Settings Set){
	Set->set1 = 1;
	Set->test = 3;
};

void main(void){
	Settings mystr;
	testing(mystr);
	printf("%d, %d\n", mystr.set1, mystr.test);
}

Вы же так любите оптимизатор, дак люзайте его как опмошника, а не как оптимизатор лалкакода.

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

Кыш от сюда! ☺

$ make lor5 
cc -O2 -pipe    -o lor5 lor5.c 
lor5.c: In function 'testing':
lor5.c:8: error: invalid type argument of '->'
lor5.c:9: error: invalid type argument of '->'
lor5.c: In function 'main':
lor5.c:12: warning: return type of 'main' is not 'int'
*** Error 1 in /home/quax/tmp (<sys.mk>:85 'lor5')

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

testing(mystr);

ничего, что структура на входе в функцию скопируется?

testing(mystr);
Set->set1 = 1;

ты это компилировать пробовал, профи

Stil ★★★★★
()
Последнее исправление: Stil (всего исправлений: 1)
Ответ на: комментарий от joy4eg

На точно таком же коде ловлю мусор. Похоже что первые два комментатора правы... Спасибо, друзья! Сейчас исправлюсь

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

Спасибо за наглядность, добрый человек!

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

Отличается только тем, что в структуре указатели на int, сейчас трудно проверить старую версию, так как до треда перевернул все структуры и переменные в глобальные, а заново неправильно делать лень. В функции работало нормально по struct->var, а вот вне ее по struct.var = мусор. Плюс структура == вместилище переменных GKeyFile'а, со всеми вытекающими - тут я вижу что делаю, а там неизвестно как что написано...

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

что в структуре указатели на int

А под них память была выделена ?
Еще нужно было эти указатели разыменовывать перед присваиванием (например, *a = 1), в противном же случае, Вы записываете туда адрес, а по этому адресу может быть что угодно, в том числе и Ваш мусор :)

joy4eg ★★★★★
()

Начнем с того: тебе её на стеке нужно или в куче?

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

вообще-то я думал, что в структуре будет храниться, что-то отличное от int... но если был не прав, то все гораздо проще:

#include <stdio.h>

typedef struct newfile {
        int set1, test;
} Settings;

void testing(Settings * Set)
{
        Set->set1 = 1;
        Set->test = 3;
};

void main(void)
{
        Settings mystr;
        testing(&mystr);                // &mystr, mystr
        printf("%d, %d\n", mystr.set1, mystr.test);
}

metawishmaster ★★★★★
()
Ответ на: комментарий от superhackkiller1997
#include <stdio.h> 
typedef struct newfile{
	 int set1, test;
} Settings;

inline void testing(Settings Set){
	Set.set1 = 1;
	Set.test = 3;
};

void main(void){
	Settings mystr;
        mystr.set1 = 0;
        mystr.test = 0;
	testing(mystr);
	printf("%d, %d\n", mystr.set1, mystr.test);
}

с -O3 выхлоп, как и ожидался, 0,0. //Хотя я знаю, что это вброс. :)

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

Нет, она не скопируется.

Скопируется, скопируется. Структуры тоже в стек по значению передавать можно. Марш учебники читать!

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

Ну что же ты так по-слоновьи разрушаешь такой замечательный образ? А я верил в тебя.

Non eadem est.

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

gchar определен как typedef char gchar;

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

typedef struct newfile {
    char *var;
    int set1, test;
} Settings;

#define MAXSZ 512
void testing(Settings * Set, char * msg)
{
    unsigned len = strnlen(msg, MAXSZ);

    Set->var = (char *) malloc((len + 1) * sizeof(char));
    if (!Set->var)
        return;
    strncpy(Set->var, msg, len);
    Set->set1 = 1;
    Set->test = 3;
};

void main(void)
{
    Settings mystr;
    testing(&mystr, "I will read books about C");   //сорри, неудержался :)
    if (!mystr.var)
        return;
    printf("%d, %d, %s\n", mystr.set1, mystr.test, mystr.var);
    free(mystr.var);    // тут необязательно, но для каноничности
}
metawishmaster ★★★★★
()
Ответ на: комментарий от beastie

stdlib.h - вторая сверху...
а варнинг там другой:
$ cc minakov.c -o minakov --std=c99
minakov.c: In function ‘testing’:
minakov.c:13:2: warning: implicit declaration of function ‘strnlen’ [-Wimplicit-function-declaration]

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

дык «так повелось» %)
к тому же, лишняя предосторожность... хорошо для более реальных ситуаций, я думаю

metawishmaster ★★★★★
()
Последнее исправление: metawishmaster (всего исправлений: 1)
Ответ на: комментарий от beastie

Потому что якобы так легче это потом портировать на Плюсы, где автокаста из void* нет.

Для меня бо́льшая загадка, почему в sizeof malloc'а продолжают вбивать тип, а не *<тот указатель, что слева от присваивания>.

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

Дануладно - я с просоня недописал то, что хотел, а вы на меня накинулись.

да там нужен ретурн и присваивание для такой функции.

А со структурами фейл, ибо структуры больше, чем с 2 или 3-мя елементами конпелятор не умеет раскидывать по регистрам вменяемо. Объясни мне почему, я уже давно хотел узнать.

Я перерыл всё аби amd64, мануал гцц, но так и не нашел причины, почему он 2елементра передаёт вменяемо через регистры, а для после 3-4 юзает тухлыйтек.

Ну и да - стек не нужен.

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

Тогда для тебя будет открытием, что параметры не везде передаются через регистры. В *BSD, например, параметры передаются только через стек. А вопрос о том, что из этих двух подходов быстрее, вообще открытый.

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

Всё, надоело. Я не знаю, что такое «лалка», но это теперь официально «5.1 Нецензурные выражения». Замечу — буду буйствовать.

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 1)
Ответ на: комментарий от unt1tled

компилятор проглотил, да и ладно. Чем меньше кода в примере - тем быстрее помогут же

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

Для меня вообще загадка, почему это многие всё ещё делают.

Привычка, видать, компилировать C-код компилятором C++.

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

Есть мнение, что если писать переменную, а не имя типа, то упрощается рефакторинг. Например, если ты захочешь изменить тип переменной, для которой выделяешь память, то тебе не придется изменят вызов malloc.

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

но я ещё автоматическим рефакторингом руки не пачкал

Даже при ручном рефакторинге ты можешь забыть изменить тип в вызове malloc. А компилятор этого не заметит.

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

Да я и ручной то не делаю. Честно признаться я даже толком не представляю, что скрывается за этим buzz-word'ом. ☺

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

Честно признаться я даже толком не представляю, что скрывается за этим buzz-word'ом.

Например, изменить тип переменной 'foo' с 'char *' на 'wchar_t *' ☺

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

«лалка», как ни странно, происходит от LOL (кто бы мог подумать? o_O)

Почему-то школота в чатах, на форумах, в игровых чатах начала говорить оппоненту «ты лол», употребляя LOL как оскорбление.

В какой-то момент «лол» превратился в «лал», а позже «ты лол»/«ты лал» начали писать как «ты лалка».

Слово «лалка» достойно занесения в список самых отвратительных слов рунета, ИМХО.

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

Слово «…» достойно занесения в список самых отвратительных слов рунета, ИМХО.

Аминь.

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

Второе по-моему ортогонально. Лично я предпочитаю тип, а не два раза переменную писать.

И если изменится тип переменной, то можно забыть поменять его и в sizeof(some_type). В случае sizeof(var_name) такой проблемы нет.
Точнее это вообще не проблема, но она может при рефакторинге привести к ошибке.

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

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

Это удобно и при ручном рефакторинге - меньше исправлять, меньше шансов сделать баг.

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

буду краток.

Я о том, что кастить malloc не надо. Для меня вообще загадка, почему это многие всё ещё делают.

MSVS

Stil ★★★★★
()
Ответ на: буду краток. от Stil

Мда… И эти люди запрещают нам ковыряться в носу!

beastie ★★★★★
()

Структура из указателей. Но им присваивается вполне конкретное значение. Здесь и есть глюк.

Объявите структуру так и все будет хорошо.

typedef struct newfile{
	 int set1, test;
} Settings;

Еще не плохо было бы почитать что-нибудь из классики. Кериган-Ричи подойдут.

anonymous
()
19 ноября 2013 г.
Ответ на: комментарий от metawishmaster

Через три итерации чтения про структуры, плюс этот код - понял. Спасибо за советы!

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