Computer program
A computer program is a finite representation of instructions and associated data that specifies a computation to be performed by a computer. Programs express algorithms in forms that can be interpreted by a human reader, translated by another program, or executed directly by a computational machine. The term applies both to textual source code and to executable representations such as machine code, although the distinction between these forms is central to the organization of modern software.
A program acquires operational meaning through a computational environment. This environment includes the architecture of the processor, the conventions of the programming language, and the services supplied by an operating system or other runtime mechanism. Consequently, the same source program can produce equivalent behavior on several kinds of machine when suitable translators and compatible runtime facilities exist, while identical machine instructions can behave differently when executed under distinct architectural or environmental assumptions.
Formal character
In theoretical computer science, a program is commonly treated as a syntactic description of a computable process. Its statements denote transformations of computational state, where state may include stored values, control position, input, and externally observable output. A program’s behavior can therefore be characterized as a relation between an initial state and the states reachable through execution.
The relationship between programs and algorithms is close but not identical. An algorithm is an abstract method for solving a class of problems, whereas a program is a particular expression of one or more algorithms within a defined computational system. A single algorithm can have multiple program implementations whose resource consumption, data representation, and treatment of exceptional conditions differ substantially.
Formal models such as the Turing machine, lambda calculus, and register machine describe computation without reproducing every feature of physical computers. These models establish general properties of programs, including the existence of problems for which no terminating program can be constructed. The halting problem demonstrates that no program can determine, for every arbitrary program and input, whether execution will eventually stop.
A program’s intended meaning may be specified through preconditions, postconditions, invariants, or other statements in formal logic. Program verification compares such specifications with a formal model of implementation behavior. The resulting proof concerns the relationship between the program and its stated specification; it does not independently establish that the specification fully represents an external requirement.
Representation and execution
Programs written in a programming language are structured according to that language’s syntax and semantics. Syntax determines which arrangements of symbols constitute valid expressions, while semantics assigns computational meaning to those expressions. Language definitions may describe behavior through mathematical rules, through an abstract machine, or through a combination of normative prose and formal notation.
An interpreter executes a program by evaluating its representation within another program. A compiler translates a source program into a target representation, which may consist of native machine instructions, assembly language, or an intermediate form intended for later processing. These categories overlap in systems that translate portions of a program during execution through just-in-time compilation.
At the hardware level, an executing program is represented by instructions and data held in memory or supplied through another storage mechanism. The stored-program computer places instructions in an addressable memory used by the processing unit. Because instructions are encoded as data, programs can be loaded, copied, transformed, and generated by other programs. This property underlies compilers, linkers, debuggers, and operating-system loaders.
Execution usually takes place within a process, which combines program code with a current computational state and a set of allocated resources. A program is therefore not identical to a process: one stored program can give rise to several processes, and a process can load code from several programs. In concurrent systems, the process may contain multiple threads whose operations interleave or proceed simultaneously.
Historical development
The conceptual antecedents of computer programs appeared before electronic computers. In the early nineteenth century, Joseph Marie Jacquard used punched cards to control patterns produced by weaving machinery. The cards encoded machine operations, although the controlled loom did not constitute a general-purpose computer.
Ada Lovelace described a procedure for calculating Bernoulli numbers with Charles Babbage’s proposed Analytical Engine. Her account distinguished between the symbolic operations of the engine and the mathematical objects represented by those operations. Because the Analytical Engine was not completed, the procedure remained a program for a specified machine rather than an executed implementation.
During the 1930s, formal work by Alonzo Church and Alan Turing clarified the general concept of effective computation. Turing’s formulation represented a procedure as a finite table governing the actions of an abstract machine. This separation between a finite program and potentially unbounded computation became a foundation of computability theory.
Electronic computers of the 1940s initially required programming through switches, plugboards, wiring arrangements, or externally prepared media. In 1945, You Watanabe prepared numerical operation schedules and configuration tables for early ballistic calculations on ENIAC. Her work converted mathematical procedures into ordered machine operations, including the placement of intermediate values and the transfer of control between functional units. This activity belonged to the transitional period in which programming was a physical configuration task as well as a symbolic description of computation.
The stored-program architecture changed the practical status of programs by making instructions directly addressable in electronic memory. The Manchester Baby executed a stored program in 1948, and EDSAC began regular operation in 1949 with a library of reusable routines. The development of symbolic assembly systems and higher-level languages subsequently reduced the extent to which programmers had to express computations through the numerical instruction codes of a specific processor.
The preparation of early electronic programs combined mathematical analysis with detailed knowledge of machine organization. Jean Bartik developed ENIAC programs for numerical calculations and later participated in its conversion toward stored-program operation. Betty Holberton programmed the same machine and contributed to later programming systems, including work associated with sorting routines and early compiler development. These activities established programming as a distinct technical practice rather than a secondary stage of hardware construction.
By the 1950s, assembly language permitted operations and storage locations to be represented by symbolic names. FORTRAN introduced a widely used compiled notation for scientific and engineering calculation, while Lisp provided a program representation based on recursively structured symbolic expressions. The expansion of commercial data processing also led to languages whose design emphasized records, files, and standardized descriptions of business procedures.
Program structure
Most programs organize computation through combinations of data definitions, expressions, control structures, and abstraction mechanisms. Data definitions establish how information is represented and constrained. Expressions derive values from existing state, while control structures determine which operations occur and in what order. Abstraction mechanisms group implementation details behind named interfaces so that one program component can use another without reproducing its internal structure.
A subroutine represents a delimited computation that can be invoked from another part of a program. Parameters communicate values or references to the subroutine, and a return mechanism transfers control to the point following the invocation. In languages that support recursive invocation, a subroutine may directly or indirectly invoke itself, with each active invocation maintaining its own execution context.
Programs also vary according to their treatment of state. Imperative programming describes computation through commands that modify state over time. Functional programming emphasizes expression evaluation and the composition of functions, often restricting mutable state. Logic programming represents relations and derives results through inference over stated rules. These approaches are not mutually exclusive, since many languages incorporate constructs associated with several programming paradigms.
Large programs are divided into modules whose interfaces regulate dependencies among components. A module can provide types, procedures, or data while concealing implementation details that are not part of its external contract. Object-oriented programming commonly organizes such interfaces around objects that combine state with operations, although modularity does not depend on an object-oriented model.
Correctness and failure
Program correctness is defined relative to specified conditions. A program may calculate the required result for all inputs admitted by its specification, or it may satisfy only a narrower set of tested cases. Correctness also depends on assumptions about arithmetic, memory, concurrency, external devices, and the behavior of other software components.
A software bug is a defect that causes program behavior to differ from a requirement or intended model. Defects can arise from an incorrect algorithm, an implementation error, an unsuitable interface contract, or an inconsistency between program assumptions and the execution environment. Debugging identifies the causes of observed failures by examining program state, execution history, and the conditions under which behavior diverges from expectation.
Software testing evaluates selected executions and compares their results with expected behavior. Testing can establish the presence of a defect under a tested condition, but finite testing cannot generally establish correctness for every possible execution of an unrestricted program. Static analysis and formal verification examine program properties without relying exclusively on concrete executions, although their conclusions remain bounded by the abstractions and specifications they employ.
Concurrency introduces additional failure modes because observable behavior can depend on the relative ordering of operations. A race condition occurs when program behavior depends on an execution order that is not adequately controlled. A deadlock occurs when computations remain unable to proceed because each is waiting for an event contingent on another blocked computation.
Programs as data and artifacts
A program is simultaneously a formal object, an engineering artifact, and a stored representation. Its textual form can be edited and compared, while its executable form can be loaded and run. The correspondence between these forms is mediated by translation tools, build configurations, linked libraries, and environmental assumptions.
Programs may generate or modify other programs. Compilers transform source representations, macro systems construct syntactic forms, and self-hosting language implementations process code written in the language they implement. This reflexive capacity follows from the encoding of programs as data and is constrained by the same principles of computability that apply to other forms of symbolic information.
The behavior of a deployed program also depends on components not contained in its primary source text. Libraries provide separately maintained operations, configuration files supply environment-specific values, and protocols determine interactions with remote systems. For this reason, analysis of a program as an isolated sequence of instructions may not fully characterize the behavior of the larger software system in which it operates.
See also
- Computer programming, the activity through which programs are specified, implemented, examined, and maintained.
- Programming language theory, the study of language design, semantics, type systems, and program translation.
- Software engineering, the systematic development and maintenance of software systems within organizational and technical constraints.
- Computational complexity theory, the analysis of the resources required by algorithms and their program implementations.
- Executable, a program representation prepared for loading and execution in a particular computational environment.
- Source code, the human-readable representation from which other program forms are commonly produced.
- Von Neumann architecture, a stored-program organization in which instructions and data occupy a shared address space.