Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

180
Visualizações
When should I pass or return a struct by value?

A struct can be either passed/returned by value or passed/returned by reference (via a pointer) in C.

The general consensus seems to be that the former can be applied to small structs without penalty in most cases. See Is there any case for which returning a structure directly is good practice? and Are there any downsides to passing structs by value in C, rather than passing a pointer?

And that avoiding a dereference can be beneficial from both a speed and clarity perspective. But what counts as small? I think we can all agree that this is a small struct:

struct Point { int x, y; };

That we can pass by value with relative impunity:

struct Point sum(struct Point a, struct Point b) {
  return struct Point { .x = a.x + b.x, .y = a.y + b.y };
}

And that Linux's task_struct is a large struct:

https://github.com/torvalds/linux/blob/b953c0d234bc72e8489d3bf51a276c5c4ec85345/include/linux/sched.h#L1292-1727

That we'd want to avoid putting on the stack at all costs (especially with those 8K kernel mode stacks!). But what's about middling ones? I assume structs smaller than a register are fine. But what about these?

typedef struct _mx_node_t mx_node_t;
typedef struct _mx_edge_t mx_edge_t;

struct _mx_edge_t {
  char symbol;
  size_t next;
};

struct _mx_node_t {
  size_t id;
  mx_edge_t edge[2];
  int action;
};

What is the best rule of thumb for determining whether a struct is small enough that it's safe to pass it around by value (short of extenuating circumstances such as some deep recursion)?

Lastly please don't tell me that I need to profile. I'm asking for a heuristic to use when I'm too lazy/it's not worth it to investigate further.

EDIT: I have two followup questions based on the answers so far:

  1. What if the struct is actually smaller than a pointer to it?

  2. What if a shallow copy is the desired behavior (the called function will perform a shallow copy anyway)?

EDIT: Not sure why this got marked as a possible duplicate as I actually link the other question in my question. I'm asking for clarification on what constitutes a small struct and am well aware that most of the time structs should be passed by reference.

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

On small embedded architectures (8/16-bitters) -- always pass by pointer, as non-trivial structures don't fit into such tiny registers, and those machines are generally register-starved as well.

On PC-like architectures (32 and 64 bit processors) -- passing a structure by value is OK provided sizeof(mystruct_t) <= 2*sizeof(mystruct_t*) and the function does not have many (usually more than 3 machine words' worth of) other arguments. Under these circumstances, a typical optimizing compiler will pass/return the structure in a register or register pair. However, on x86-32, this advice should be taken with a hefty grain of salt, due to the extraordinary register pressure a x86-32 compiler must deal with -- passing a pointer may still be faster due to reduced register spilling and filling.

Returning a structure by value on PC-likes, on the other hand, follows the same rule, save for the fact that when a structure is returned by pointer, the structure to be filled out should be passed in by pointer as well -- otherwise, the callee and the caller are stuck having to agree on how to manage the memory for that structure.

over 4 years ago · Santiago Trujillo Relatório

0

My experience, nearly 40 years of real-time embedded, last 20 using C; is that the best way is to pass a pointer.

In either case the address of the struct needs to be loaded, then the offset for the field of interest needs to be calculated...

When passing the whole struct, if it is not passed by reference, then

  1. it is not placed on the stack
  2. it is copied, usually by a hidden call to memcpy()
  3. it is copied to a section of memory that is now 'reserved' and unavailable to any other part of the program.

Similar considerations exist for when a struct is returned by value.

However, "small" structs, that can be completely held in a working register to two are passed in those registers especially if certain levels of optimization are used in the compile statement.

The details of what is considered 'small' depend on the compiler and the underlying hardware architecture.

over 4 years ago · Santiago Trujillo Relatório

0

Since the argument-passing part of the question is already answered, I'll focus on the returning part.

The best thing to do IMO is to not return structs or pointers to structs at all, but to pass a pointer to the 'result struct' to the function.

void sum(struct Point* result, struct Point* a, struct Point* b);

This has the following advantages:

  • The result struct can live either on the stack or on the heap, at the caller's discretion.
  • There are no ownership problems, as it is clear that the caller is responsible for allocating and freeing the result struct.
  • The structure could even be longer than what is needed, or be embedded in a larger struct.
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda