Jump to content
Sign in to follow this  
fredericopissarra

Mais coisas que estão no padrão que permitem "macetes"...

Recommended Posts

Existe uma diferença entre declarar e usar algo numa expressão. Por exemplo, a declaração:

char s[] = "fred";

Define um array s que será preenchido com 5 caracteres (o '\0' também conta), mas esses 5 caracteres não serão alocados numa sessão read-only da imagem binária (dado o literal "fred", acima).

Mas, usar uma "string" literal numa expressão, ou chamada de função, pode forçar o compilador a criar um array "read-only":

if ( ! strcmp ( s, "fred" ) ) do_something();

Neste caso os 5 bytes de "fred" serão colocados na sessão .rodata, obrigatoriamente, porque a função strcmp() exige o uso de um ponteiro. O mesmo acontece com a declaração:

char *s = "fred";

Sabendo que esse literal entre aspas é um atalho para uma sequência de bytes (um array), podemos comparar duas "strings" com até 8 chars (contando o '\0' final), assim [compare as funções f() e g()]:

#include <string.h>

int f( char *s ) { return ! strcmp( s, "fred" ); }

int g( char *s )
{
  long long a, b;

  a = *(long long *)s;
  b = *(long long *)"fred";

  return ( ( a & 0xffffffffffULL ) - b ) == 0;
}

A função f() é esquisita. Repare como usei o literal "fred" como ponteiro long long e o dereferenciei...

Outra coisa é que tive que mascarar os bits superiores de a, a partir do 6º byte porque, na comparação, o 5º byte precisa ser 0. f() parece mais complicada e, portanto, supostamente, o código fica mais lento, certo? Errado: Essa assertiva quase nunca é verdadeira. O tamanho e performance do código depende do que ele faz, não da quantidade de linhas e expressões que ele contém. Eis a listagem em assembly das duas rotinas:

section .rodata

ro_fredstr: db 'f', 'r', 'e', 'd', 0, 0, 0, 0

section .text

f:
  mov rsi,rdi
  lea rdi,[ro_fredstr]
  mov ecx,5
  rep cmpsb
  seta al
  sbb al,0
  test al,al
  sete al
  movzx eax,al
  ret
  
g:
  mov rax,0xffffffffff
  and rax,[rdi]
  cmp rax,[ro_fredstr]
  sete al
  movzx eax,al
  ret

Claro, isso só funciona com comparações com strings de até 8 caracteres e com tamanho previamente conhecido (temos que criar a máscara de acordo!). Não é lá muito "usável" no dia-a-dia, mas ilustra o ponto de que podemos criar rotinas mais rápidas usando esse tipo de macete.

Outro detalhe interessante sobre strings literais em expressões: Como elas podem ser alocadas como arrays e a especificação nos diz, explicitamente, que o operador [] é um atalho para uma expressão usando ponteiros, isto é:

c = a[i];  // isto é a mesma coisa que...
c = *(a+i); // ... isto!

Podemos escrever, sem problemas, algo assim:

c = "fred"[2]; // c será 'e'.

E como qualquer adição segue a propriedade comutativa (a+b = b+a), uma construção, válida, mas até mais estranha, é possível:

c = 2["fred"];

Interessante, não?

  • Curtir 3
  • l33t 1

Share this post


Link to post
Share on other sites
a = *(long long *)s;
 b = *(long long *)"fred";

so nao entedi essa parte.

sei que o "*" antes do "(" significa que e um ponteiro, mas "long long *" complicou.

aof

abc.

Share this post


Link to post
Share on other sites
Posted (edited)
44 minutos atrás, Aof disse:

a = *(long long *)s;
 b = *(long long *)"fred";

so nao entedi essa parte.

sei que o "*" antes do "(" significa que e um ponteiro, mas "long long *" complicou.

Nope... o * antes de (long long *) é um operador de indireção... ele pega o valor inteiro na variável ponteiro e o usa para obter o dado para onde esse endereço aponta. O (long long *) é um operador de casting (conversão) que, neste caso, converte o ponteiro do tipo char * para o tipo long long *.

Assim, o operador * será obrigado a acessar 8 bytes (de um long long), não apenas 1 (de um char).

Edited by fredericopissarra
  • Curtir 2

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...