Jump to content

Funções static


Dani jojo

Recommended Posts

Olá a todos,

Existe algum motivo ou problema em declarar uma função estática num header?

Já sabemos que uma função deste género tem internal linkage mas ao definirmos dentro do Source o compilador não se queixa. Se voltarmos a incluir o ficheiro num segundo Source file o compilador vai dar erro e dizer que a função não está definida.

Aqui temos duas alternativas interpretamos o facto de ser estática como sendo única e exclusivamente para uso local ou ré-definimos a função no segundo source 🙂

Qual o problema de criar uma segunda definição nesse segundo source file. Ao fazer include é uma vez que a função é estática irá ser criada uma cópia.

Aparentemente nada de mal poderá acontecer.

Ou seja, se excluirmos questões de optimização existe realmente problema em definir a função estática dentro do header? Obrigado pelo suporte.

Link to comment
Share on other sites

Se a função é estática, não é suposto ser chamada de outro ficheiro. Se precisas de a chamar de outro ficheiro, então claramente não a devias ter declarado como estática dado que faz parte da interface daquele "ficheiro"/"programa"/"utilitário"/whatever o ficheiro representa.

Reimplementar novamente noutro ficheiro é de longe a pior opção.

Link to comment
Share on other sites

6 horas atrás, HappyHippyHippo disse:

eu gostava era de saber qual a razão da necessidade da declaração da função como estática ...

Não é importante para a questão uma vez que o compilador e a por conseguinte a própria linguagem nos permite fazer tal.

Mas só para dar algum contexto eu por regra quando defino uma função como static faço-o dentro do source file uma vez que pretendo que essa função seja usada na translation unit na qual a defino.

No entanto, já me aconteceu ver isso definido num header file. E isto fez-me pensar qual o impacto de se fazer tal coisa. 

Obrigado a todos pelo suporte e o tempo dispensado à minha questão.

  • Vote 1
Link to comment
Share on other sites

2 hours ago, Dani jojo said:

Não é importante para a questão uma vez que o compilador e a por conseguinte a própria linguagem nos permite fazer tal.

que não é importante, dizes tu. eu acho bem pertinente

se a função é declarada como estática no header e terá o seu código duplicado nos vários object files, basta tirar o static para isso não acontecer (e fazer como toda a gente faz que é fazer a implementação no .c)

queres um exemplo de algo que a linguagem premite e não deve ser feito ?

olha para o C++, a multipla herança é como caminhar em casca de ovos : permite, mas o mais fácil é fazer algo que nunca deve ser feito ...

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

27 minutos atrás, HappyHippyHippo disse:

que não é importante, dizes tu. eu acho bem pertinente

Para a pergunta que eu fiz não é importante porque já todos percebemos a utilização.

28 minutos atrás, HappyHippyHippo disse:

se a função é declarada como estática no header e terá o seu código duplicado nos vários object files, basta tirar o static para isso não acontecer (e fazer como toda a gente faz que é fazer a implementação no .c)

Não é exactamente isso que acontece... A declaração é duplicada a definição não!!!! É static por isso tem Internal linkage.

O que acontece é que terás que a definir novamente se a quiseres usar!!!!! Mas podes até ter duas funções com a mesma "assinatura" mas implementações diferentes certo?

Mais se fizeres include noutro source file e tentares usar essa função sem a definires o compilador vai-te dizer que a função não está definida!

Aquilo que tu queres dizer acontece se fizeres a definição no header que não é bem aquilo que eu perguntei. 

32 minutos atrás, HappyHippyHippo disse:

queres um exemplo de algo que a linguagem premite e não deve ser feito ?

olha para o C++, a multipla herança é como caminhar em casca de ovos : permite, mas o mais fácil é fazer algo que nunca deve ser feito ...

Não é o exemplo mais feliz para o caso... podias citar o uso do new... raw pointers... operador de indexação.... agora múltipla herança????

Só é problemático se o teu código é mal modelado, falta de arquitectura consistente, etc, etc!

  • Vote 1
Link to comment
Share on other sites

1 hour ago, Dani jojo said:

Não é exactamente isso que acontece... A declaração é duplicada a definição não!!!! É static por isso tem Internal linkage.

O que acontece é que terás que a definir novamente se a quiseres usar!!!!! Mas podes até ter duas funções com a mesma "assinatura" mas implementações diferentes certo?

Mais se fizeres include noutro source file e tentares usar essa função sem a definires o compilador vai-te dizer que a função não está definida!

Aquilo que tu queres dizer acontece se fizeres a definição no header que não é bem aquilo que eu perguntei. 

certo ... estás a dizer que este exemplo não acontece no teu computador:

static.h

#pragma once

static int func(void) {
    return 10;
}

foo.h

#pragma once

int foo(void);

bar.h

#pragma once

int bar(void);

foo.c

#include "static.h"
#include "foo.h"

#include <stdio.h>

int foo(void) {
    return printf("foo : %d\n", func());
}

bar.c

#include "static.h"
#include "bar.h"

#include <stdio.h>

int bar(void) {
    return printf("bar : %d\n", func());
}

shell:

$ objdump -t ./obj/src/bar.o

./obj/src/bar.o:     file format pe-x86-64

SYMBOL TABLE:
[  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x0000000000000000 bar.c
File
[  2](sec  1)(fl 0x00)(ty  20)(scl   3) (nx 1) 0x0000000000000000 func  <----------------------------------
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[  4](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x000000000000000b bar
[  5](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .text
AUX scnlen 0x2c nreloc 2 nlnno 0
[  7](sec  2)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0
[  9](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 11](sec  4)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .xdata
AUX scnlen 0x14 nreloc 0 nlnno 0
[ 13](sec  5)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .pdata
AUX scnlen 0x18 nreloc 6 nlnno 0
[ 15](sec  6)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .rdata
AUX scnlen 0xa nreloc 0 nlnno 0
[ 17](sec  7)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .debug_info
AUX scnlen 0x16f nreloc 5 nlnno 0
[ 19](sec  8)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .debug_abbrev
AUX scnlen 0x51 nreloc 0 nlnno 0
[ 21](sec  9)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .debug_aranges
AUX scnlen 0x30 nreloc 2 nlnno 0
[ 23](sec 10)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .debug_line
AUX scnlen 0x59 nreloc 1 nlnno 0
[ 25](sec 12)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .rdata$zzz
AUX scnlen 0x11 nreloc 0 nlnno 0
[ 27](sec 13)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .debug_frame
AUX scnlen 0x68 nreloc 4 nlnno 0
[ 29](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x0000000000000000 printf

$ objdump -t ./obj/src/foo.o

./obj/src/foo.o:     file format pe-x86-64

SYMBOL TABLE:
[  0](sec -2)(fl 0x00)(ty   0)(scl 103) (nx 1) 0x0000000000000000 foo.c
File
[  2](sec  1)(fl 0x00)(ty  20)(scl   3) (nx 1) 0x0000000000000000 func <------------------------------------------------------
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[  4](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x000000000000000b foo
[  5](sec  1)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .text
AUX scnlen 0x2c nreloc 2 nlnno 0
[  7](sec  2)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0
[  9](sec  3)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 11](sec  4)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .xdata
AUX scnlen 0x14 nreloc 0 nlnno 0
[ 13](sec  5)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .pdata
AUX scnlen 0x18 nreloc 6 nlnno 0
[ 15](sec  6)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .rdata
AUX scnlen 0xa nreloc 0 nlnno 0
[ 17](sec  7)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .debug_info
AUX scnlen 0x16f nreloc 5 nlnno 0
[ 19](sec  8)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .debug_abbrev
AUX scnlen 0x51 nreloc 0 nlnno 0
[ 21](sec  9)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .debug_aranges
AUX scnlen 0x30 nreloc 2 nlnno 0
[ 23](sec 10)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .debug_line
AUX scnlen 0x59 nreloc 1 nlnno 0
[ 25](sec 12)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .rdata$zzz
AUX scnlen 0x11 nreloc 0 nlnno 0
[ 27](sec 13)(fl 0x00)(ty   0)(scl   3) (nx 1) 0x0000000000000000 .debug_frame
AUX scnlen 0x68 nreloc 4 nlnno 0
[ 29](sec  0)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x0000000000000000 printf
1 hour ago, Dani jojo said:

Não é o exemplo mais feliz para o caso... podias citar o uso do new... raw pointers... operador de indexação.... agora múltipla herança????

Só é problemático se o teu código é mal modelado, falta de arquitectura consistente, etc, etc!

o exemplo é optimo : apresenta algo que a linguagem deixa fazer, deixando uma porta escancarada para problemas sérios.

os teus exemplos ficam a saber a pouco quando a sua utilização é obrigatória para resolução de certos problemas. a multipla heranla foi demonstrado por outras linguagem que é dispensável.

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.