{"action":"opened","issue":{"url":"https://api.github.com/repos/pjreddie/darknet/issues/75","repository_url":"https://api.github.com/repos/pjreddie/darknet","labels_url":"https://api.github.com/repos/pjreddie/darknet/issues/75/labels{/name}","comments_url":"https://api.github.com/repos/pjreddie/darknet/issues/75/comments","events_url":"https://api.github.com/repos/pjreddie/darknet/issues/75/events","html_url":"https://github.com/pjreddie/darknet/issues/75","id":242355947,"number":75,"title":"Avoid passing and returning structs by value","user":{"login":"imaami","id":3589345,"avatar_url":"https://avatars1.githubusercontent.com/u/3589345?v=3","gravatar_id":"","url":"https://api.github.com/users/imaami","html_url":"https://github.com/imaami","followers_url":"https://api.github.com/users/imaami/followers","following_url":"https://api.github.com/users/imaami/following{/other_user}","gists_url":"https://api.github.com/users/imaami/gists{/gist_id}","starred_url":"https://api.github.com/users/imaami/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/imaami/subscriptions","organizations_url":"https://api.github.com/users/imaami/orgs","repos_url":"https://api.github.com/users/imaami/repos","events_url":"https://api.github.com/users/imaami/events{/privacy}","received_events_url":"https://api.github.com/users/imaami/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2017-07-12T12:00:34Z","updated_at":"2017-07-12T12:00:34Z","closed_at":null,"body":"Whenever a new copy of a struct is not expressly required, a function should receive a struct by reference (pointer to struct) instead of by value. Also, returning a struct by value is likely always unnecessary as well. Passing large structs by value adds a lot of copying back and forth from one function call to another, and additionally it makes it very difficult to understand whether a given function should modify the original struct instance or just receive its content as input values.\r\n\r\nA made-up (but working and compilable) example:\r\n\r\n```c\r\n#include <stdio.h>\r\n#include <stddef.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n\r\nstruct foo {\r\n\tsize_t size;\r\n\tchar *data;\r\n\t// Unused variables below become needless baggage during pass-by-value\r\n\tint barstool;\r\n\tint hippopotamus;\r\n\tint large_trout_in_vacuum;\r\n\tchar put_stuff_here_for_no_reason[32];\r\n};\r\n\r\nstatic void print_object(struct foo *ptr) {\r\n\tprintf(\"{ size=%d, data=%p }\\n\", ptr->size, ptr->data);\r\n}\r\n\r\nstatic void print_object_unnecessarily_by_value(struct foo val) {\r\n\tprintf(\"{ size=%d, data=%p }\\n\", val.size, val.data);\r\n}\r\n\r\nstatic void alter_object(struct foo *ptr) {\r\n\tptr->size += 13;\r\n\tptr->data = realloc(ptr->data, ptr->size);\r\n}\r\n\r\nstatic struct foo alter_object_unnecessarily_by_value(struct foo val) {\r\n\tval.size += 13;\r\n\tval.data = realloc(val.data, val.size);\r\n\treturn val;\r\n}\r\n\r\nint main(int argc, char **argv) {\r\n\tstruct foo obj;\r\n\tmemset(&obj, 0, sizeof(obj));\r\n\tprint_object(&obj);\r\n\t\r\n\t// Avoid doing these\r\n\tobj = alter_object_unnecessarily_by_value(obj);\r\n\tprint_object_unnecessarily_by_value(obj);\r\n\r\n\t// Do these instead\r\n\talter_object(&obj);\r\n\tprint_object(&obj);\r\n\r\n\tif (obj.data != NULL) free(obj.data);\r\n\tmemset(&obj, 0, sizeof(obj));\r\n\r\n\treturn 0;\r\n}\r\n```"}}
{"actor":{"display_login":"imaami"}}