Respostas:
Usado corretamente, pode ser uma técnica útil.
Digamos que você tenha um subsistema complexo e crítico para o desempenho com uma interface pública relativamente pequena e muitos códigos de implementação não reutilizáveis. O código tem vários milhares de linhas, uma centena de funções privadas e muitos dados privados. Se você trabalha com sistemas embarcados não triviais, provavelmente lida com essa situação com frequência suficiente.
Sua solução provavelmente será em camadas, modular e desacoplada e esses aspectos podem ser representados e reforçados de forma útil pela codificação de diferentes partes do subsistema em arquivos diferentes.
Com C, você pode perder muito fazendo isso. Quase todos os conjuntos de ferramentas fornecem otimização decente para uma única unidade de compilação, mas são muito pessimistas sobre qualquer coisa declarada externa.
Se você colocar tudo em um módulo de origem C, você obtém -
Melhorias no desempenho e no tamanho do código - as chamadas de função serão incorporadas em muitos casos. Mesmo sem inlining, o compilador tem oportunidades de produzir código mais eficiente.
Dados de nível de link e ocultação de função.
Evitar a poluição do namespace e seu corolário - você pode usar nomes menos pesados.
Compilação e ligação mais rápidas.
Mas você também obtém uma bagunça profana quando se trata de editar este arquivo e você perde a modularidade implícita. Isso pode ser superado dividindo a fonte em vários arquivos e incluindo-os para produzir uma única unidade de compilação.
Você precisa impor algumas convenções para gerenciar isso de forma adequada. Isso vai depender de seu conjunto de ferramentas até certo ponto, mas algumas dicas gerais são -
Coloque a interface pública em um arquivo de cabeçalho separado - você deve fazer isso de qualquer maneira.
Tenha um arquivo .c principal que inclua todos os arquivos .c subsidiários. Isso também pode incluir o código para a interface pública.
Use protetores de compilador para garantir que cabeçalhos privados e módulos de origem não sejam incluídos por unidades de compilação externas.
Todos os dados e funções privados devem ser declarados estáticos.
Mantenha a distinção conceitual entre os arquivos .c e .h. Isso aproveita as convenções existentes. A diferença é que você terá muitas declarações estáticas em seus cabeçalhos.
Se seu conjunto de ferramentas não impõe nenhuma razão para não fazê-lo, nomeie os arquivos de implementação privados como .c e .h. Se você usar proteções de inclusão, elas não produzirão nenhum código e não introduzirão novos nomes (você pode acabar com alguns segmentos vazios durante a ligação). A grande vantagem é que outras ferramentas (por exemplo, IDEs) tratarão esses arquivos de maneira adequada.
esta ok? sim vai compilar
é recomendado? não - os arquivos .c são compilados em arquivos .obj, que são vinculados após a compilação (pelo vinculador) no executável (ou biblioteca), portanto, não há necessidade de incluir um arquivo .c em outro. O que você provavelmente deseja fazer é criar um arquivo .h que liste as funções / variáveis disponíveis no outro arquivo .c e incluir o arquivo .h
Não.
Dependendo do seu ambiente de construção (você não especifica), você pode descobrir que ele funciona exatamente da maneira que você deseja.
No entanto, existem muitos ambientes (ambos IDEs e muitos Makefiles feitos à mão) que esperam compilar * .c - se isso acontecer, você provavelmente acabará com erros de linker devido a símbolos duplicados.
Como regra, esta prática deve ser evitada.
Se você absolutamente deve # incluir o código-fonte (e geralmente deve ser evitado), use um sufixo de arquivo diferente para o arquivo.
Pensei em compartilhar uma situação em que minha equipe decidiu incluir arquivos .c. Nossa arquitetura consiste basicamente em módulos que são desacoplados por meio de um sistema de mensagens. Esses manipuladores de mensagens são públicos e chamam muitas funções de trabalho estáticas locais para fazer seu trabalho. O problema surgiu ao tentar obter cobertura para nossos casos de teste de unidade, já que a única maneira de exercitar esse código de implementação privado era indiretamente por meio da interface de mensagem pública. Com algumas funções de trabalhador até os joelhos na pilha, isso acabou sendo um pesadelo para conseguir uma cobertura adequada.
Incluir os arquivos .c nos deu uma maneira de alcançar a engrenagem da máquina que estávamos testando.
Você pode usar o compilador gcc no linux para vincular dois arquivos c em uma saída. Suponha que você tenha dois arquivos c, um é 'main.c' e o outro é 'support.c'. Portanto, o comando para vincular esses dois é
gcc main.c support.c -o main.out
Por isso, dois arquivos serão ligados a uma única saída main.out Para executar a saída, o comando será
./main.out
Se você estiver usando a função em main.c, que é declarada no arquivo support.c, você deve declará-la em main também usando a classe de armazenamento externo.
Você pode incluir corretamente os arquivos .C ou .CPP em outros arquivos de origem. Dependendo do seu IDE, você geralmente pode evitar a ligação dupla olhando as propriedades dos arquivos de origem que deseja incluir, geralmente clicando com o botão direito e clicando em propriedades, e desmarcar / marcar compilar / vincular / excluir da construção ou qualquer outra opção talvez. Ou você não poderia incluir o arquivo no próprio projeto, assim o IDE nem saberá que ele existe e não tentará compilá-lo. E com makefiles você simplesmente não colocaria o arquivo nele para compilar e vincular.
EDIT: Desculpe, eu fiz uma resposta em vez de uma resposta para outras respostas :(
A linguagem C não proíbe esse tipo de #include, mas a unidade de tradução resultante ainda precisa ser C. válida
Não sei qual programa você está usando com um arquivo .prj. Se você estiver usando algo como "make" ou Visual Studio ou qualquer outra coisa, apenas certifique-se de definir sua lista de arquivos a serem compilados sem aquele que não pode ser compilado independentemente.
Incluir o arquivo C em outro arquivo é legal, mas não é aconselhável, a menos que você saiba exatamente por que está fazendo isso e o que está tentando alcançar.
Tenho quase certeza que se você postar aqui o motivo pelo qual por trás de sua pergunta a comunidade encontrará para você outra forma mais adequada de atingir seu objetivo (observe o "quase", pois é possível que essa seja a solução dado o contexto )
A propósito, perdi a segunda parte da pergunta. Se o arquivo C for incluído em outro arquivo e ao mesmo tempo incluído no projeto, você provavelmente acabará com o problema de símbolo duplicado porque vincular os objetos, ou seja, a mesma função será definida duas vezes (a menos que sejam todos estáticos).