Jump to content

fredericopissarra

Membros
  • Content Count

    243
  • Joined

  • Last visited

Community Reputation

190 Excellent

Personal Information

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Grande Felipe, você é muito mais paciente que eu... também pensei em passar o troço pelo pré-processador (cpp - c pre processor)... mas não tive paciência pra isso! 🙂
  2. Note que tentei explicar o troço sob o ponto de vista da aplicação de ponto flutuante... Acredito que dá uma visão interessante do uso de floats para o estudante... Explicando a otimização da divisão inteira transformada em multiplicação: #BitIsMyth wp.me/pudbF-1MI []s Fred
  3. Outra obra de arte do IOCCC (Jon Thingvold, em 1996) Não faço a MENOR ideia de como esse troço funciona: #define O B F U S C A T E D #define I 8;}t(p){r(p?W:o);XClearWindow(V,m);}main(i,f)char**f;{M((T(h=f), #define K Y(o,XMapRaised(V,e);)x=3;x--;)for(y=3;y--;r(G))XMapRaised(V,R[D] #define N z(x+i,(z(H-x-i,x),x)))x<i||z(x-i,x)|z(H-x+i,x)Y(W,)l=k;l>20&&l>x #define XIMOfIC Z;XID(*w)()=XCreateWindow,m,e,o[2],W[2],G[2],R[2][O]);}GC*g #define E (++D)));}r(XID*z){XSetWindowBackgroundPixmap(V=d[D],m=R[D][x][y],z[ #define L ;XStoreName(V,e=w(V,RootWindow(V,s),0,0,152,152,2,0,1,0,0,0),"II"+D #define B 3][3];Display*V,*d[2];char**h,k=25,b[2500],H=50,D,s,x,y,i;T(){float #define S +k),z(k-P=w(V,e,H*x,H*y,H,H,1,0,1,0,2048,&c));}XEvent J;M(){XFlush( #define Y(z,y) ;for(z[D]=XCreatePixmapFromBitmapData(Q,x=0,H*H);x<H;x++)y for( #define A x][y]&&!b[x+k*y]++?t(D),t(!(D^=1)):D);M();}z(x,y){b[x/8+y*7]|=1<<x%I #define P x,y)-z(y,x+k)+z(y,k-x)*z(x+k,y=H-y),z(k-x,y),z(y,k-x),z(y,k+x)K[x][y] #define Q V,e,b,H,H,BlackPixel(V,s),WhitePixel(V,s),DefaultDepth(V,s)),memset(b #define C d[!D]);x=3;for(XNextEvent(V,&J);x--;)for(y=3;y--;J.xany.window==R[D][ #define F l;XSetWindowAttributes c;s=XDefaultScreen(V=d[D]=XOpenDisplay(*(h+=!! #define U *h)))L)Y(G,)i=c.event_mask=4;i--;x+i>H||N;l-=.5)z(x+k,y=sqrt(l*l-x*x) #include <math.h> #include <string.h> #include <X11/Xlib.h> Só funciona nos "unixes" (por causa do X11)... Para compilar: $ gcc -O2 -ansi -o jonth jonth.c -lX11 -lm Para compilar no Solaris é necessário acrescentar -lsocket. Note que o código inteiro só tem definições lexicas (#define)... cadê a porcaria do main() como função (está lá na definição de I)? 🙂 Esse programinha abrirá 2 janelas no X11 (sem argumentos ambas abrirão no DISPLAY default)... elas podem ser direcionadas para hosts diferentes... por exemplo: $ ./jonth host1:0 host2:0 Onde 'host1' e 'host2' podem ser IPs ou nomes de hosts...
  4. Num forum que participo alguém pediu para resolver um problema escolar envolvendo uma "bola que quica" (bouncing ball)... Minha resposta, na forma dessa obra de arte (IOCCC): /* ball.c */ /* Compile with: 'gcc -ansi -o ball ball.c -lm' */ /* Works on linux */ #include <stdio.h> #include <math.h> #include <unistd.h> #include <sys/ioctl.h> main() { short a[4];ioctl (0,TIOCGWINSZ,&a);int b,c,d=*a,e=a[1];float f,g, h,i=d/2+d%2+1,j=d/5-1,k=0,l=e/ 2,m=d/4,n=.01*e,o=0,p=.1;while ( printf("\x1b[H\x1B[?25l"),!usleep( 79383)){for (b=c=0;h=2*(m-c)/i,f=- .3*(g=(l-b)/i)+.954*h,c<d;c+=(b=++ b%e)==0)printf("\x1B[%dm ",g*g>1-h *h?c>d-j?b<d-c||d-c>e-b?40:100:b<j ||b>e-j?40:g*(g+.6)+.09+h*h<1?100: 47:((int)(9-k+(.954*g+.3*h)/sqrt (1-f*f))+(int)(2+f*2))%2==0?107 :101);k+=p,m+=o,o=m>d-2*j? -.04*d:o+.002*d;n=(l+= n)<i||l>e-i?p=-p ,-n:n;}} Infelizmente o forum não usa fonte monoespaçada para códigos-fonte (deveria)... dai, eis a captura do código acima, em imagem:
  5. Tentei converter para mobi, mas a formatação é toda perdida (e formatação é importante nesse material). Portanto, vai ficar em PDF mesmo... sorry...
  6. Não gosto muito de formatos mobi e epub por questão de formatação. No momento não estou com os fontes do arquivo aqui, depois gero o mobi pra ver como fica. Os PDFs estão protegidos por senha (senha GRANDE) e talvez a tentativa de conversão não seja bem sucedida à partir dos PDFs, mas pode-se tentar usar o "calibre" (utilitário ebook-convert). PS: Eu também não sei a senha de cabeça... ela é gerada de forma automatizada (via APG) e (acho) tem uns 64 caracteres de tamanho... Tipo: $ apg -a1 -m64 -n1 yv%:_Hq,6jf[rBmChxxnNuT:3{uhJ[0lfBgNUYXMC5qH9<Y;?M"g(coTt!$*D_M+ Não recomendo o método da força bruta para quebrar a senha... numa base 94 com 32 chars temos, aproximadamente, 1,9*10¹²⁷ combinações possíveis.
  7. Recomendo instalar um cross compiler no seu PC (gcc-8-mips-linux-gnu, no Linux) e dar uma olhada no código em ASM gerado por esse códigozinho: // test.c // Compile com mips-linux-gnu-gcc-8 -O2 -S test.c // acrescente -DDEBUG para que a função leapyear() não fique inline. // Será definida em outro lugar para não poluir o // assembly gerado. extern void show_year( int ); #ifdef DEBUG __attribute__((noinline)) #endif static int leapyear( int year ) { // anos bissextos não são simplesmente aqueles divisíveis por 4 apenas! // Os anos divisíveis por 4 (e não por 100) e os anos divisíveis por 400 é que são bissextos. return ( ! ( year % 4 ) && ( year % 100 ) ) || ( ! ( year % 400 ) ); } // A função assume que ystart é menor ou igual a yend. void show_nonleapyears( int ystart, int yend ) { int i; for ( i = ystart; i <= yend; i++ ) // Só mostra os anos não-bissextos. if ( ! leapyear( i ) ) show_year( i ); }
  8. fredericopissarra

    x86 e x64

    Códigos x86-64 tendem a ter um cadinhozinho de performance melhor por um dois simples fatos: 1- A convenção de chamada usa registradores, ao invés da pilha, demandando menos acesso à memória; 2- Pode-se manipular duas vezes mais dados (registradores de 64 bits) numa tacada só... O ganho, aliás, não é exacerbado... digamos de uns 5% a 10% mais rápido, dependendo do caso.
  9. Yep... a opção -S serve para gerar o código em ASM a partir do código em C, então o programa em test.c tem que ser compilável. Você pode usar -fverbose-asm se quiser os aqueles montes de comentários, mas para análise do código gerado ele não é necessário.
  10. Não estou dizendo que sua aproximação está errada ou que seja ruim. Só o que estou dizendo é que, talvez, ela possa falhar em algum momento. Limitar os testes a uma faixa que "dá certo" não quer dizer que o algoritmo vai funcionar para toda a faixa... A otimização que postei (que não foi minha, vi num forum e achei interessante) funciona para qualquer valor N, inteiro, de qualquer precisão... O sujeito que bolou isso percebeu que quando um valor é primo e é maior que 4, ele pode ser expresso por 6n+/-k (onde k={0..5}, ou seja, k=n mod 6)... mas, k não pode ser 0, 2, 3 ou 4 (senão teremos valor par [k=0,2,4] ou divisível por 3 [k=3]). Assim, k só pode ser 1 ou 5. Agora, tomemos n=1 e obteremos 5 (6*1-1) e 7 (6*1+1), e 1 (6*1-5) e 11 (6*1+5). Esses são candidatos a primazia... Se você fizer n=2 (n+1), teremos 11 (6*2-1), 13 (6*2+1), 7 (6*2-5) e 17 (6*2+5). Claramente (e podemos comprovar isso por congruência) testes com k=5 são cobertos pelos mesmos testes onde k=1 e podemos descartar k=5. Dai, o testes de primazia só precisam ser feitos com 6n-1 e 6n+1. Por isso o loop começa em 5, avançamos k em 2 unidades (de -1 para +1), testamos o próximo e testamos de novo... avançamos 4 unidades (por causa do 6n) e fazemos tudo de novo... O que descrevi acima é uma prova por "indução matemática" e é garantido que o resultado seja o mesmo para qualquer N... Teríamos que provar, de maneira semelhante, que sua aproximação é válida para qualquer N inteiro positivo e é isso que eu não tenho certeza (porque não pensei à respeito) que esteja correto. Quanto ao crivo de Erastótenes. Basicamente ele realiza as divisões apenas com os valores prímos previamente encontrados, no loop, mas precisa armazená-los num grande array. Esse é o método mais "rápido" (e um pouquinho mais complicado), mas potencialemente usa muita memória para isso. No caso, mesmo não usando arrays, a cadeia de testes ficaria muito grande e é bom lembrar que cada divisão é LENTA. Uma rotina com 2 divisões não é cria lá grande perda de velocidade, mas uma com 8 divisões dentro do loop tem o potencial de ser bem lenta. [[]]ão Fred
  11. Well... Talvez, temos que verificar (a validade do algoritmo anterior é um cadinho mais complicada do que eu postei - desse ai, eu não sei)... Mas, de qualquer maneira, temos que parar em algum lugar, não? Senão o algoritmo degenera para o crivo de Erastótenes.
  12. Só um aviso aos amigos... esse livro não é a versão definitiva. Note que é a versão 0.33.9 (nem sequer é a versão 1). Ele não contém tudo o que eu gostaria de falar sobre a mesclagem de C e ASM na arquitetura x86-64 e talvez seja prolixo em alguns pontos (também não foi tão bem revisado assim)... Anyway, espero que seja útil pra alguém... 😉 Ele e o "Linguagem..." foram ensaios para a confecção de um livro mais e mais completo que ainda estou escrevendo (e esse novo livro eu pretendo publicar)...
  13. Só um aviso aos amigos... esse livro não é a versão definitiva. Note que é a versão 0.8.5 (nem sequer é a versão 1). Ele não contém tudo o que eu gostaria de falar sobre ASM e talvez seja prolixo em alguns pontos (também não foi tão bem revisado assim)... Anyway, espero que seja útil pra alguém... 😉 Ele e o "Dicas" foram ensaios para a confecção de um livro mais e mais completo que ainda estou escrevendo (e esse novo livro eu pretendo publicar)...
  14. Já eu, @bratergames, nunca parei de estudar e estou com os ARM da vida, mas não "apenas"... 🙂 Tio Fred só sumiu do facebook (nunca mais entro naquela bosta) e do discord do mente binária...
  15. Artigo original: https://is.gd/55lrpk Alguns de vocês já devem ter lido por aqui e feito experiências com relação ao “endereço” base de um array. Considere o seguinte array: int a[] = { 1, 2, 3, 4 }; O identificador a é, de forma bastante comum, encarado como o ponteiro para o início do array. De fato, a especificação ISO 9989 nos diz que o operador [] pode ser, seguramente, interpretado como a = *(a + i). Mas, há uma distinção sutil aqui: O identificador a não é um ponteiro! Ele é interpretado como sendo um… “Porra, tio Fred, assim você dá um nó na minha cachola!”. O problema aparece quando usamos o operador & (endereço-de): #include <stdio.h> int a[] = { 1, 2, 3 4 }; int main( void ) { printf( "a=%p, &a=%p\n", a, &a ); } Ao compilar e executar isso você verá que os endereços impressos são os mesmos. Como pode um ponteiro apontar para uma coisa e um ponteiro para um ponteiro apontar para a mesma coisa? Não pode! O fato é que a, usando usado em expressões, é convertido em um ponteiro, mas ele não é um. O símbolo a aqui é um array “identificado” pelo nome a. Parece que não há diferença, não é? Então, vejamos esse outro exemplo: Se a e &a forem, de fato, o mesmo ponteiro, apontar para o próximo item do array deveria fornecer o mesmo endereço, não é? #include <stdio.h> int a[] = { 1, 2, 3 4 }; int main( void ) { printf( "a=%p, &a=%p\n", a, &a ); printf( "next(a)=%p, next(&a)=%p\n", a + 1, &a + 1 ); } Compilando e executando você obtém algo assim: $ cc -O2 -o test test.c $ ./test a=0x563c50e5a010, &a=0x563c50e5a010 next(a)=0x563c50e5a014, next(&a)=0x563c50e5a020 Ué?! Por que &a+1 resultou em um endereço diferente de a+1? Note que em nossa tentativa de obter o endereço do próximo item com o ponteiro, no primeiro caso obtemos, corretamente, o endereço 4 bytes além da base, mas no segundo (usando &a), obtemos o endereço além do final do array (16 bytes além da base)… Isso ocorre porque os tipos dos ponteiros convertidos à partir de a são diferentes… O primeiro ponteiro, a+1 é do tipo int *, o segundo, do tipo int (*)[4]. Ou seja, a e &a fornecem o mesmo endereço porque estamos obtendo o endereço do identificador a, que aponta para o início do array. No primeiro caso (a) o identificador é convertido para um ponteiro, no segundo (&a) obtemos o “endereço-do array identificado por a. Sim, você pode assumir que o identificador de um array seja um ponteiro para sua base, se usar apenas o nome do identificador como ponteiro (não o seu endereço), mas, além do problema acima, existe outro: O identificador de um array definido carrega consigo, em tempo de compilação, o tamanho do array. Se você usar o operador sizeof com o identificador a, obterá 16 (4 vezes o tamanho de um int), no exemplo acima… Se a fosse apenas um ponteiro, obteria 4 (i386) ou 8 (x86-64) que, aliás, é o que obterá se tentar obter sizeof(&a).
×
×
  • Create New...