Sou um programador autodidata, caso essa pergunta seja respondida no CS 101. Aprendi e usei muitas línguas, principalmente para meu uso pessoal, mas ocasionalmente para coisas profissionais.
Parece que estou sempre correndo contra a mesma parede quando me deparo com problemas na programação. Por exemplo, acabei de fazer uma pergunta em outro fórum sobre como lidar com um ponteiro para matriz que foi retornado por uma função. Inicialmente, estou pensando que simplesmente não conheço a técnica adequada que os designers de C ++ configuraram para lidar com a situação. Mas, pelas respostas e discussões que se seguem, vejo que realmente não entendo o que acontece quando algo é 'devolvido'.
Quão profundo é o nível de entendimento do processo de programação que um bom programador deve alcançar?
Respostas:
Não. Ninguém entende o que está acontecendo no nível do hardware.
Os sistemas de computador são como cebolas - há muitas camadas, e cada uma depende da camada abaixo dela para suporte. Se você é o cara que trabalha em uma das camadas externas, não deve se importar muito com o que acontece no meio da cebola. E isso é bom, porque o meio da cebola está sempre mudando. Contanto que a camada ou camadas que suportam sua camada específica continuem com a mesma aparência e suportem sua camada, você estará bem.
Mas, novamente ...
Sim. Quero dizer, você não precisa entender o que realmente está acontecendo dentro da cebola, mas ajuda muito ter um modelo mental de como é o interior de uma cebola típica. Talvez não seja a parte mais profunda, onde você tem portas compostas por transistores e coisas assim, ou a próxima camada ou duas, onde você tem microcódigo, relógio, unidades de decodificação de instruções etc. As próximas camadas, no entanto, são onde você tenho registros, a pilha e a pilha. Essas são as camadas mais profundas em que você tem muita influência sobre o que acontece - o compilador traduz seu código em instruções executadas nesse nível e, se você quiser, geralmente pode percorrer essas instruções e descobrir o que "realmente" está acontecendo.
A maioria dos programadores experientes tem uma versão ligeiramente de conto de fadas dessas camadas na cabeça. Eles ajudam a entender o que o compilador está falando quando informa que houve uma "exceção de endereço inválido" ou um "erro de estouro de pilha" ou algo assim.
Se você estiver interessado, leia um livro sobre arquitetura de computadores. Nem precisa ser um livro particularmente novo - os computadores digitais estão trabalhando aproximadamente da mesma maneira há muito tempo. Quanto mais você aprender sobre o interior da cebola, mais espantado ficará que alguma dessas coisas funcione! Aprender (aproximadamente) o que está acontecendo nas camadas inferiores torna a programação menos misteriosa e, de alguma forma, mais mágica. E realmente, mais divertido.
Outra coisa que você pode ver são as cebolas embutidas. Quero dizer, sistemas embarcados. Há várias plataformas incorporadas que são bastante fáceis de usar: Arduino e BASIC Stamp são dois exemplos. Estes são basicamente pequenos microprocessadores com muitos recursos internos. Você pode pensar nelas como cebolas com menos camadas do que o seu PC de mesa típico, portanto, é possível obter uma compreensão bastante completa do que está acontecendo em todo o sistema, do hardware ao software.
fonte
Você não está falando sobre o nível de hardware, mas sobre o que o compilador realmente faz com o que você diz para fazer.
Você certamente precisa desse nível de entendimento para descobrir o que deu errado quando não é óbvio, especialmente ao lidar com uma situação de perda de memória.
fonte
Noções básicas sobre memória de programa! = Noções básicas sobre hardware
Compreendendo a hierarquia de memória == Compreendendo o hardware
Para responder sua pergunta genérica: Depende. Não é demais entender o hardware, mas entendê-lo não ajudará em todos os casos.
Com base no seu exemplo, você só precisa entender mais sobre como a memória é dividida e como é organizada quando você está executando um programa. A compreensão do hardware não o ajudará nesse sentido, porque a memória (como visível para um programa) nem mesmo representa o hardware de verdade, graças à magia da memória virtual.
Se você estava curioso sobre problemas de desempenho com base na ordem em que acessa a memória, AGORA você se beneficiaria com a compreensão do hardware, a hierarquia de memória, falhas de cache, falhas de página e toda a gloriosa bondade maravilhosa que vem do hardware.
fonte
Se você não decidir a aprender um pouco de assembler, você provavelmente deve aprender algo como 6502 assembler em um Commodore 64 (emulado, é claro), ou 68000 em um Amiga.
Você pode ter uma idéia do Commodore 64 aqui ...
http://thepiratebay.org/torrent/4609238/Tag3-Saal2-Slot16_00--ID2874-the_ultimate_commodore_64_talk-Main
O clássico livro "tudo o que você precisa saber" é o descrito aqui ...
http://reprog.wordpress.com/2010/03/12/programming-books-part-3-programming-the-commodore-64/
Provavelmente, você pode encontrar uma digitalização em PDF se olhar em volta.
O IMO, 6502 é mais fácil que o Z80 e 68000 é mais fácil que o 8086 - conjuntos de instruções mais regulares etc.
Mas a CPU é apenas um aspecto do hardware. Além disso, uma CPU moderna é uma fera massivamente diferente e faz coisas transparentes mesmo do ponto de vista dos compiladores - como apresentar um espaço de endereço virtual.
Uma vantagem particular do 6502 no C64 é que não apenas a CPU é simples, mas também há algumas muito simples de se mexer com o hardware. Eu me divertia muito brincando com o chip de música SID.
Então - provavelmente é um exercício que vale a pena se você não gastar muito tempo com ele. Eu aprendi o 6502 assembler como minha segunda língua quando eu tinha 14 anos, logo após o Commodore Basic. Mas, na maioria das vezes, ele está obtendo esse modelo de trabalho muito simples, para que você possa adicionar idéias mais sofisticadas com um mínimo de mal-entendido.
Algumas coisas úteis que você pode aprender trabalhando em assembler ...
Uma razão particular pela qual eu recomendo é obter uma melhor intuição da maneira como as etapas simples operam inteiramente determinística e mecanicamente e totalmente sem inteligência ou bom senso. Basicamente, acostumar-se ao modelo de execução imperativa em sua forma mais pura e teimosamente ignorante.
Precisamente quão útil é conhecer a maioria dessas coisas agora, no entanto, é uma pergunta difícil.
Uma coisa que você não aprenderá é como jogar bem com uma hierarquia de memória. Essas máquinas antigas geralmente tinham um modelo de memória simples, sem camadas de cache e sem memória virtual. Você também não aprenderá muito sobre concorrência - eles certamente eram maneiras de lidar com isso, mas na maioria das vezes significava interrupções. Você não precisava se preocupar com mutexes etc.
Às vezes, um modelo mental de como essas coisas uma vez trabalhou, ou de como funciona a montadora, pode até enganar. Por exemplo, pensar em um ponteiro C como um endereço pode levar a problemas de comportamento indefinidos. Normalmente, o ponteiro AC é implementado como um número inteiro contendo um endereço, mas não há garantia de que isso seja verdade. Por exemplo, em algumas plataformas bizarras, ponteiros diferentes podem apontar para diferentes espaços de endereço. Isso se torna importante quando você deseja fazer aritmética ou lógica bit a bit com dois ponteiros.
A menos que você tenha uma dessas plataformas bizarras, talvez não pense que se importa com isso - mas os compiladores hoje em dia têm cada vez mais probabilidade de explorar o comportamento indefinido dos padrões para otimização.
Portanto, um modelo mental da arquitetura do sistema pode ser útil, mas ainda é importante codificar para as especificações da linguagem, não para um modelo hipotético que sua linguagem e plataforma possam não respeitar.
Finalmente, muitas coisas úteis de modelos mentais vêm da idéia de como os compiladores geram código - e a geração de código para linguagens modernas é muito diferente dos compiladores bastante triviais disponíveis na época.
Este é o meu livro favorito por isso ...
http://dickgrune.com/Books/MCD_1st_Edition/
Juntamente com o material sobre análise e ASTs, etc, abrange a geração de código para uma variedade de paradigmas de linguagem - imperativos, OOP, funcionais, lógicos, paralelos e distribuídos - e também para gerenciamento de memória. Se você quiser saber como as chamadas de método polimórfico funcionam sem se atolar nos detalhes do conjunto de instruções da CPU, um livro como este é seu amigo - e haverá uma nova edição em breve.
fonte
Vinte anos atrás, isso era importante, mas não tanto agora - há muito mais camadas de abstração entre software e hardware moderno.
É útil saber coisas como precisar de vários threads para tirar proveito de vários núcleos ou que usar mais memória do que existe no sistema é uma coisa ruim, mas além disso, você realmente não precisa disso, a menos que seja seu trabalho escrever essas abstrações camadas.
O restante da sua pergunta sugere que você pode estar mais preocupado com o compilador do que com o hardware, que é um pouco diferente. Você pode encontrar casos em que isso é importante, mas esses tendem a ser triviais (a recursão infinita não funciona muito bem) ou o tipo de casos extremos em que você pode se sentir bem em resolvê-lo, mas provavelmente nunca terá o mesmo problema novamente.
fonte
Ajuda muito a conhecer e entender a abstração apresentada pelo hardware, e um pouco da idéia geral sobre como essa ilusão é criada - mas tentar realmente entender como o hardware moderno realmente funciona é uma tremenda quantidade de trabalho a partir do qual você ' é provável que tenha apenas um retorno mínimo.
Se você perdoa um desvio menor: isso me lembra algo que notei há alguns anos atrás. Décadas atrás (até o final dos anos 70), a maioria das pessoas pensava que os computadores estavam um passo à frente da mágica - dificilmente afetados pelas leis da física, capazes de todo tipo de coisa que fazia pouco sentido real, e assim por diante. Na época, passei um bom tempo tentando (principalmente sem sucesso) convencer as pessoas de que não, elas não eram mágicas. Na verdade, eram máquinas razoavelmente comuns que faziam um número limitado de coisas com muita rapidez e confiabilidade, mas eram extremamente mundanas.
Atualmente, a visão da maioria das pessoas sobre computadores mudou. Agora eles são bastante comuns - a ponto de algumas pessoas muito comuns terem uma compreensão prática deles. Apenas por exemplo, um tempo atrás, enquanto eu estava jantando, eu vi / ouvi um garçom e garçonete no intervalo discutindo o que ela deveria receber em seu novo computador. O conselho que ele estava dando era inteiramente razoável e realista.
Minha visão dos computadores também mudou. Eu fui para o Hot Chips e, antes disso, o Fórum do Microprocessador, que remonta a meados dos anos 90. Provavelmente sei mais sobre hardware de microprocessador do que pelo menos 99% dos programadores - e, sabendo o que faço, vou dizer o seguinte: eles não são mais comuns. Eles fazem quase quebrar as leis da física. Eu fiz muitos testes de baixo nível e posso dizer isso com certeza: superar a ilusão criada pela CPU e mostrar como o hardware realmente funciona é muitas vezes incrivelmente difícil. Eu gostaria de poder postar uma foto de uma de nossas configurações com um computador enterrado sob cabos de não menos de quatro analisadores lógicos apenas para medir adequadamente um aspecto de como o cache funciona em uma CPU moderna (para não mencionar uma programação realmente exigente para garantir que o que medimos seja exatamente o que a CPU estava fazendo e nada mais).
fonte
Idiomas diferentes funcionam em diferentes níveis de abstração do hardware. C e C ++ são de nível muito baixo. As linguagens de script, por outro lado, exigem que você saiba menos sobre os detalhes subjacentes.
No entanto, eu ainda diria que, em todos os casos, quanto mais você souber, melhor será o programador. Parte da programação é ser capaz de manipular vários níveis de abstração ao mesmo tempo.
Se você está programando em C ++, precisa ter um bom entendimento de como uma CPU moderna funciona, pelo menos no nível de abstração em que o compilador trabalha. (Há coisas acontecendo dentro da CPU que também são transparentes para o compilador).
fonte
Gostaria de acrescentar um ponto sobre o design geral de linguagens de nível superior como C.
Em geral, acho seguro dizer que essas linguagens podem ser vistas como implementando uma máquina abstrata e, de fato, foi assim que o próprio Dennis Ritchie descreveu como C funciona e como o design específico da máquina abstrata de C a tornou uma linguagem mais portátil. Como tal, ter algum entendimento da arquitetura do computador e do funcionamento no nível da máquina, pode ser extremamente útil para entender também a máquina abstrata de uma linguagem.
Documento da DMR Portabilidade de programas C e o sistema UNIX é o primeiro que lembro de discutir o modelo de máquina (abstrato) para C.
Acho que o artigo da DMR sobre a história e o desenvolvimento de C também é extremamente útil para mostrar como o hardware real afeta o design da linguagem e talvez seja também um exemplo do design inicial da linguagem de programação: The Development of the C Language
fonte