본문 바로가기
컴퓨터/deep dive into systems

1. By the C, by the C, by the Beautiful C-1.1. Getting Started Programming in C

by book_lover 2025. 1. 26.

1. By the C, by the C, by the Beautiful C

This chapter presents an overview of C programming written for students who have some experience programming in another language. It’s specifically written for Python programmers and uses a few Python examples for comparison purposes (Appendix 1 is a version of Chapter 1 for Java programmers). However, it should be useful as an introduction to C programming for anyone with basic programming experience in any language.

C is a high-level programming language like other languages you might know, such as Python, Java, Ruby, or C++. It’s an imperative and a procedural programming language, which means that a C program is expressed as a sequence of statements (steps) for the computer to execute and that C programs are structured as a set of functions (procedures). Every C program must have at least one function, the main function, which contains the set of statements that execute when the program begins.

The C programming language is less abstracted from the computer’s machine language than some other languages with which you might be familiar. This means that C doesn’t have support for object-oriented programming (like Python, Java, and C++) or have a rich set of high-level programming abstractions (such as strings, lists, and dictionaries in Python). As a result, if you want to use a dictionary data structure in your C program, you need to implement it yourself, as opposed to just importing the one that is part of the programming language (as in Python).

C’s lack of high-level abstractions might make it seem like a less appealing programming language to use. However, being less abstracted from the underlying machine makes C easier for a programmer to see and understand the relationship between a program’s code and the computer’s execution of it. C programmers retain more control over how their programs execute on the hardware, and they can write code that runs more efficiently than equivalent code written using the higher-level abstractions provided by other programming languages. In particular, they have more control over how their programs manage memory, which can have a significant impact on performance. Thus, C remains the de facto language for computer systems programming where low-level control and efficiency are crucial.

We use C in this book because of its expressiveness of program control and its relatively straightforward translation to assembly and machine code that a computer executes. This chapter introduces programming in C, beginning with an overview of its features. Chapter 2 then describes C’s features in more detail.

 

이 장에서는 다른 프로그래밍 언어를 경험해본 학생들을 대상으로 C 프로그래밍에 대한 개요를 제공합니다. 특히 Python 프로그래머를 위해 작성되었으며, Python 예제를 몇 가지 비교 목적으로 사용합니다(부록 1은 Java 프로그래머를 위한 1장의 버전입니다). 그러나 기본적인 프로그래밍 경험이 있는 누구에게나 C 프로그래밍 입문서로 유용할 것입니다.C는 여러분이 알고 있을 만한 Python, Java, Ruby, C++와 같은 고급 프로그래밍 언어 중 하나입니다. C는 명령형(imperative)이고 절차적(procedural)인 프로그래밍 언어로, 이는 C 프로그램이 컴퓨터가 실행할 일련의 명령문(단계)으로 표현되며, C 프로그램이 함수(절차)의 집합으로 구성된다는 것을 의미합니다. 모든 C 프로그램에는 최소 하나의 함수가 있어야 하며, 이 함수는 프로그램이 시작될 때 실행되는 명령문 집합을 포함하는 main 함수입니다.C 프로그래밍 언어는 여러분이 익숙할 수 있는 다른 언어들보다 컴퓨터의 기계어(machine language)와의 추상화 수준이 낮습니다. 이는 C가 객체 지향 프로그래밍(Python, Java, C++처럼)을 지원하지 않으며, 고급 프로그래밍 추상화(예: Python의 문자열, 리스트, 딕셔너리 등)가 풍부하지 않다는 것을 의미합니다. 따라서 C 프로그램에서 딕셔너리 데이터 구조를 사용하려면, Python처럼 내장된 것을 가져다 쓰는 대신 직접 구현해야 합니다.C의 고급 추상화 부족은 덜 매력적인 언어처럼 보이게 할 수도 있습니다. 그러나 기계와의 추상화 수준이 낮다는 점은 프로그래머가 프로그램 코드와 컴퓨터 실행 간 관계를 더 잘 이해할 수 있도록 해줍니다. C 프로그래머는 하드웨어에서 프로그램이 실행되는 방식을 더 많이 제어할 수 있으며, 다른 고급 언어에서 제공하는 추상화를 사용하여 작성한 동등한 코드보다 더 효율적으로 실행되는 코드를 작성할 수 있습니다. 특히 메모리 관리 방식을 더 세밀하게 제어할 수 있기 때문에 성능에 큰 영향을 미칠 수 있습니다. 이러한 이유로 C는 낮은 수준의 제어와 효율성이 중요한 컴퓨터 시스템 프로그래밍에서 사실상의 표준 언어로 남아 있습니다.이 책에서는 프로그램 제어의 표현력과 컴퓨터가 실행하는 어셈블리 및 기계 코드로의 비교적 간단한 번역 때문에 C를 사용합니다. 이 장에서는 C의 기능 개요를 시작으로 C 프로그래밍을 소개하며, 2장에서는 C의 기능을 더 자세히 설명합니다.

1.1. Getting Started Programming in C

Let’s start by looking at a "hello world" program that includes an example of calling a function from the math library. In Table 1 we compare the C version of this program to the Python version. The C version might be put in a file named hello.c (.c is the suffix convention for C source code files), whereas the Python version might be in a file named hello.py.

 

Table 1. Syntax Comparison of a Small Program in Python and C. Both the C version and Python version are available for download.

"Hello World" 프로그램과 수학 라이브러리의 함수를 호출하는 예제를 포함한 프로그램을 살펴보겠습니다. 표 1에서는 이 프로그램의 C 버전과 Python 버전을 비교합니다. C 버전은 일반적으로 hello.c라는 파일에 작성되며, Python 버전은 hello.py 파일에 작성될 수 있습니다.

/*
    The Hello World Program in C
 */

/* C math and I/O libraries */
#include <math.h>
#include <stdio.h>

/* main function definition: */
int main(void) {
    // statements end in a semicolon (;)
    printf("Hello World\n");
    printf("sqrt(4) is %f\n", sqrt(4));

    return 0;  // main returns value 0
}​
'''
    The Hello World Program in Python
'''

# Python math library
from math import *


# main function definition:
def main():
    # statements on their own line
    print("Hello World")
    print("sqrt(4) is %f" % (sqrt(4)))

# call the main function:
main()

 

Notice that both versions of this program have similar structure and language constructs, albeit with different language syntax. In particular:

Comments:

  • In Python, multiline comments begin and end with ''', and single-line comments begin with #.
  • In C, multiline comments begin with /* and end with */, and single-line comments begin with //.

Importing library code:

  • In Python, libraries are included (imported) using import.
  • In C, libraries are included (imported) using #include. All #include statements appear at the top of the program, outside of function bodies.

Blocks:

  • In Python, indentation denotes a block.
  • In C, blocks (for example, function, loop, and conditional bodies) start with { and end with }.

The main function:

  • In Python, def main(): defines the main function.
  • In C, int main(void){ } defines the main function. The main function returns a value of type int, which is C’s name for specifying the signed integer type (signed integers are values like -3, 0, 1234). The main function returns the int value 0 to signify running to completion without error. The void means it doesn’t expect to receive a parameter. Future sections show how main can take parameters to receive command line arguments.

Statements:

  • In Python, each statement is on a separate line.
  • In C, each statement ends with a semicolon ;. In C, statements must be within the body of some function (in main in this example).

Output:

  • In Python, the print function prints a formatted string. Values for the placeholders in the format string follow a % symbol in a comma-separated list of values (for example, the value of sqrt(4) will be printed in place of the %f placeholder in the format string).
  • In C, the printf function prints a formatted string. Values for the placeholders in the format string are additional arguments separated by commas (for example, the value of sqrt(4) will be printed in place of the %f placeholder in the format string).

There are a few important differences to note in the C and Python versions of this program:

Indentation: In C, indentation doesn’t have meaning, but it’s good programming style to indent statements based on the nested level of their containing block.

Output: C’s printf function doesn’t automatically print a newline character at the end like Python’s print function does. As a result, C programmers need to explicitly specify a newline character (\n) in the format string when a newline is desired in the output.

main function:

  • A C program must have a function named main, and its return type must be int. This means that the main function returns a signed integer type value. Python programs don’t need to name their main function main, but they often do by convention.
  • The C main function has an explicit return statement to return an int value (by convention, main should return 0 if the main function is successfully executed without errors).
  • A Python program needs to include an explicit call to its main function to run it when the program executes. In C, its main function is automatically called when the C program executes.
Python과 C 프로그램의 구조와 언어 구성 요소는 서로 다른 문법을 사용하지만 유사한 점이 많습니다. 이를 한국어로 번역하면 다음과 같습니다: 주석:
  • Python에서는 여러 줄 주석은 '''로 시작하고 끝납니다. 한 줄 주석은 #로 시작합니다.
  • C에서는 여러 줄 주석은 /*로 시작하고 */로 끝납니다. 한 줄 주석은 //로 시작합니다.
라이브러리 코드 가져오기:
  • Python에서는 import 키워드를 사용하여 라이브러리를 가져옵니다.
  • C에서는 #include를 사용하여 라이브러리를 가져옵니다. 모든 #include 문은 프로그램의 최상단, 함수 본문 외부에 위치합니다.
블록:
  • Python에서는 들여쓰기가 블록을 나타냅니다.
  • C에서는 블록(예: 함수, 반복문, 조건문 본문)은 {로 시작하고 }로 끝납니다.
메인 함수:
  • Python에서는 def main():으로 메인 함수를 정의합니다.
  • C에서는 int main(void){ }로 메인 함수를 정의합니다.
    • 메인 함수는 int 타입의 값을 반환하며, 이는 C에서 부호 있는 정수형(signed integer)을 나타냅니다(예: -3, 0, 1234).
    • 메인 함수는 오류 없이 완료되었음을 나타내기 위해 0을 반환합니다.
    • void는 매개변수를 받지 않음을 의미합니다. 이후 섹션에서 메인이 명령줄 인수를 받는 방법을 설명합니다.
문장(Statements):
  • Python에서는 각 문장이 별도의 줄에 작성됩니다.
  • C에서는 각 문장이 세미콜론(;)으로 끝납니다. 또한 모든 문장은 반드시 어떤 함수 본문(예: main)에 포함되어야 합니다.
출력:
  • Python의 print 함수는 서식화된 문자열을 출력합니다. 서식 문자열의 자리 표시자(예: %f)에 해당하는 값은 % 뒤에 콤마로 구분된 값 목록에서 가져옵니다(예: sqrt(4)의 값이 %f 자리 표시자에 출력됨).
  • C의 printf 함수도 서식화된 문자열을 출력합니다. 그러나 자리 표시자에 대한 값은 추가 인수로 전달되며, 콤마로 구분됩니다(예: sqrt(4)의 값이 %f 자리 표시자에 출력됨).
Python과 C 프로그램 간 몇 가지 중요한 차이점:
  1. 들여쓰기:
    • C에서는 들여쓰기가 의미를 가지지 않지만, 블록 중첩 수준에 따라 들여쓰기를 사용하는 것이 좋은 프로그래밍 스타일입니다.
  2. 출력:
    • C의 printf 함수는 Python의 print 함수처럼 자동으로 줄 바꿈 문자를 추가하지 않습니다. 따라서 C 프로그래머는 출력 문자열에 명시적으로 줄 바꿈 문자(\n)를 지정해야 합니다.
  3. 메인 함수:
    • C 프로그램은 반드시 이름이 main인 함수를 가져야 하며, 반환 타입은 반드시 int여야 합니다. 이는 메인 함수가 부호 있는 정수 값을 반환한다는 의미입니다.
    • Python 프로그램은 메인 함수 이름을 반드시 main으로 할 필요는 없지만, 관례적으로 그렇게 합니다.
    • C의 메인 함수에는 명시적인 반환문(return statement)이 있어야 하며, 일반적으로 성공적으로 실행되었음을 나타내기 위해 0을 반환해야 합니다.
    • Python 프로그램은 실행 시 메인 함수를 명시적으로 호출해야 하지만, C에서는 프로그램 실행 시 메인 함수가 자동으로 호출됩니다.
 

1.1.1. Compiling and Running C Programs

Python is an interpreted programming language, which means that another program, the Python interpreter, runs Python programs: the Python interpreter acts like a virtual machine on which Python programs are run. To run a Python program, the program source code (hello.py) is given as input to the Python interpreter program that runs it. For example ($ is the Linux shell prompt):

 python hello.py

 

The Python interpreter is a program that is in a form that can be run directly on the underlying system (this form is called binary executable) and takes as input the Python program that it runs (Figure 1).

Figure 1. A Python program is directly executed by the Python interpreter, which is a binary executable program that is run on the underlying system (OS and hardware)

To run a C program, it must first be translated into a form that a computer system can directly execute. A C compiler is a program that translates C source code into a binary executable form that the computer hardware can directly execute. A binary executable consists of a series of 0’s and 1’s in a well-defined format that a computer can run.

For example, to run the C program hello.c on a Unix system, the C code must first be compiled by a C compiler (for example, the GNU C compiler, GCC) that produces a binary executable (by default named a.out). The binary executable version of the program can then be run directly on the system (Figure 2):

$ gcc hello.c
$ ./a.out

 

(Note that some C compilers might need to be explicitly told to link in the math library: -lm)

(일부 C 컴파일러는 수학 라이브러리를 명시적으로 링크하도록 지시해야 할 수도 있습니다: -lm)

$ gcc hello.c -lm

Figure 2. The C compiler (gcc) builds C source code into a binary executable file (a.out). The underlying system (OS and hardware) directly executes the a.out file to run the program.

 

 Python: 인터프리터 방식

  • Python은 인터프리터 언어로, Python 프로그램은 Python 인터프리터라는 프로그램에 의해 실행됩니다.
  • Python 인터프리터는 바이너리 실행 파일 형태로 제공되며, Python 소스 코드(예: hello.py)를 입력으로 받아 실행합니다.
  • 실행 과정:
    1. Python 소스 파일을 작성합니다.
    2. 해당 파일을 Python 인터프리터에 전달하여 실행합니다.
      예: $ python hello.py (Linux 쉘 프롬프트에서 실행)
  • Python 인터프리터는 소스 코드를 한 줄씩 읽고 즉시 실행하며, 이 과정에서 별도의 컴파일 단계가 필요하지 않습니다.

C: 컴파일 방식

  • C는 컴파일 언어로, 프로그램이 실행되기 전에 반드시 기계어로 번역된 바이너리 실행 파일 형태로 변환되어야 합니다.
  • 이 변환 작업은 C 컴파일러(예: GCC)가 수행하며, 결과물은 컴퓨터 하드웨어가 직접 실행할 수 있는 바이너리 파일입니다.
  • 실행 과정:
    1. C 소스 파일(예: hello.c)을 작성합니다.
    2. C 컴파일러를 사용해 소스 코드를 컴파일하여 바이너리 파일(기본 이름: a.out)을 생성합니다.
      예: $ gcc hello.c 또는 $ gcc hello.c -o hello
    3. 생성된 바이너리 파일을 시스템에서 직접 실행합니다.
      예: $ ./a.out 또는 $ ./hello

Python과 C의 주요 차이점

  1. 실행 방식:
    • Python은 인터프리터가 소스 코드를 직접 실행합니다.
    • C는 소스 코드를 먼저 바이너리 실행 파일로 변환한 후 실행됩니다.
  2. 속도:
    • Python은 한 줄씩 해석하고 실행하기 때문에 상대적으로 느립니다.
    • C는 미리 컴파일된 기계어를 실행하므로 속도가 빠릅니다.
  3. 컴파일 필요 여부:
    • Python은 별도의 컴파일 과정이 필요 없습니다.
    • C는 반드시 컴파일 과정을 거쳐야 합니다.
  4. 결과물:
    • Python은 소스 코드 자체가 실행됩니다.
    • C는 컴파일 후 생성된 바이너리 파일이 실행됩니다.

이러한 차이는 Python이 개발 속도와 사용 편의성에 중점을 둔 고수준 언어인 반면, C는 성능과 하드웨어 근접성을 강조한 중수준 언어라는 점에서 기인합니다.

Detailed Steps

In general, the following sequence describes the necessary steps for editing, compiling, and running a C program on a Unix system:

  1. Using a text editor (for example, vim), write and save your C source code program in a file (e.g., hello.c):
  2. $ vim hello.c
  3. Compile the source to an executable form, and then run it. The most basic syntax for compiling with gcc is:
  4. $ gcc <input_source_file>

If compilation yields no errors, the compiler creates a binary executable file named a.out. The compiler also allows you to specify the name of the binary executable file to generate using the -o flag:

$ gcc -o <output_executable_file> <input_source_file>

For example, this command instructs gcc to compile hello.c into an executable file named hello:

$ gcc -o hello hello.c

We can invoke the executable program using ./hello:

$ ./hello

Any changes made to the C source code (the hello.c file) must be recompiled with gcc to produce a new version of hello. If the compiler detects any errors during compilation, the ./hello file won’t be created/re-created (but beware, an older version of the file from a previous successful compilation might still exist).

Often when compiling with gcc, you want to include several command line options. For example, these options enable more compiler warnings and build a binary executable with extra debugging information:

$ gcc -Wall -g -o hello hello.c

Because the gcc command line can be long, frequently the make utility is used to simplify compiling C programs and for cleaning up files created by gcc. Using make and writing Makefiles are important skills that you will develop as you build up experience with C programming.

We cover compiling and linking with C library code in more detail at the end of Chapter 2.

 
 

 

C 프로그램 작성, 컴파일 및 실행 단계

텍스트 편집기를 사용하여 C 소스 코드 작성 및 저장

  • 예: vim을 사용하여 hello.c라는 파일에 소스 코드를 작성합니다.
$ vim hello.c

 

소스 코드를 실행 가능한 바이너리 형태로 컴파일

  • 기본적으로 gcc 명령어를 사용하여 소스 파일을 컴파일합니다.
$ gcc <입력_소스_파일>

 

바이너리 파일 이름 지정 (옵션)

  • -o 옵션을 사용하여 생성될 실행 파일의 이름을 지정할 수 있습니다.
$ gcc -o <출력_실행_파일> <입력_소스_파일>
#예: hello.c를 컴파일하여 hello라는 실행 파일을 생성합니다.
$ gcc -o hello hello.c

 

생성된 실행 파일 실행

  • ./를 사용하여 실행 파일을 실행합니다.
$ ./hello

 

  1. 소스 코드 수정 후 재컴파일 필요
    • 소스 코드(hello.c)를 수정한 경우, 변경 사항을 반영하려면 다시 컴파일해야 합니다.
    • 컴파일 중 오류가 발생하면 새로운 실행 파일이 생성되지 않으며, 이전 성공적으로 생성된 실행 파일은 그대로 남아 있을 수 있으니 주의해야 합니다.

추가 옵션으로 컴파일 경고 및 디버깅 정보 활성화

  • -Wall: 모든 경고 메시지를 활성화합니다.
  • -g: 디버깅 정보를 포함합니다.
$ gcc -Wall -g -o hello hello.c

 

  1. Makefile과 make 유틸리티 사용 (선택 사항)
    • 여러 번의 컴파일 명령어를 간소화하기 위해 make 유틸리티와 Makefile을 사용할 수 있습니다.
    • 이는 복잡한 프로젝트에서 특히 유용하며, 자동화된 빌드 및 정리를 지원합니다.

추가 참고 사항

  • 일부 C 컴파일러는 수학 라이브러리를 명시적으로 링크해야 할 수도 있습니다. 이 경우 -lm 옵션을 추가합니다:
$ gcc -o hello hello.c -lm
  • 컴파일 과정에서 발생하는 오류는 수정 후 다시 컴파일해야 하며, 경고 메시지(warning)는 무시 가능하지만 오류(error)는 반드시 해결해야 합니다.

1.1.2. Variables and C Numeric Types

Like Python, C uses variables as named storage locations for holding data. Thinking about the scope and type of program variables is important to understand the semantics of what your program will do when you run it. A variable’s scope defines when the variable has meaning (that is, where and when in your program it can be used) and its lifetime (that is, it could persist for the entire run of a program or only during a function activation). A variable’s type defines the range of values that it can represent and how those values will be interpreted when performing operations on its data.

In C, all variables must be declared before they can be used. To declare a variable, use the following syntax:

type_name variable_name;

A variable can have only a single type. The basic C types include char, int, float, and double. By convention, C variables should be declared at the beginning of their scope (at the top of a { } block), before any C statements in that scope.

Below is an example C code snippet that shows declarations and uses of variables of some different types. We discuss types and operators in more detail after the example.

vars.c
{
    /* 1. Define variables in this block's scope at the top of the block. */

    int x; // declares x to be an int type variable and allocates space for it

    int i, j, k;  // can define multiple variables of the same type like this

    char letter;  // a char stores a single-byte integer value
                  // it is often used to store a single ASCII character
                  // value (the ASCII numeric encoding of a character)
                  // a char in C is a different type than a string in C

    float winpct; // winpct is declared to be a float type
    double pi;    // the double type is more precise than float

    /* 2. After defining all variables, you can use them in C statements. */

    x = 7;        // x stores 7 (initialize variables before using their value)
    k = x + 2;    // use x's value in an expression

    letter = 'A';        // a single quote is used for single character value
    letter = letter + 1; // letter stores 'B' (ASCII value one more than 'A')

    pi = 3.1415926;

    winpct = 11 / 2.0; // winpct gets 5.5, winpct is a float type
    j = 11 / 2;        // j gets 5: int division truncates after the decimal
    x = k % 2;         // % is C's mod operator, so x gets 9 mod 2 (1)
}

Note the semicolons galore. Recall that C statements are delineated by ;, not line breaks — C expects a semicolon after every statement. You’ll forget some, and gcc almost never informs you that you missed a semicolon, even though that might be the only syntax error in your program. In fact, often when you forget a semicolon, the compiler indicates a syntax error on the line after the one with the missing semicolon: the reason is that gcc interprets it as part of the statement from the previous line. As you continue to program in C, you’ll learn to correlate gcc errors with the specific C syntax mistakes that they describe.

 

1.1.2. 변수와 C의 숫자형

Python과 마찬가지로, C에서도 변수를 데이터 저장을 위한 이름 있는 저장소로 사용합니다. 프로그램 변수의 **범위(scope)**와 **타입(type)**을 이해하는 것은 프로그램 실행 시 어떤 동작을 수행할지 파악하는 데 중요합니다.

  • 변수의 범위(scope): 수가 의미를 가지는 시점과 위치를 정의합니다(즉, 프로그램 내에서 변수를 사용할 수 있는 위치와 시간).
  • 변수의 생명주기(lifetime): 변수의 생존 기간을 정의합니다(예: 프로그램 전체 실행 동안 유지되거나 특정 함수 실행 중에만 존재).

변수의 타입(type):
수가 표현할 수 있는 값의 범위와 해당 값이 연산 시 어떻게 해석될지를 정의합니다.

C에서 변수 선언

C에서는 변수를 사용하기 전에 반드시 선언해야 합니다. 변수 선언 구문은 다음과 같습니다:

type_name variable_name;
  • 변수는 단일 타입만 가질 수 있습니다.
  • 기본 C 타입에는 char, int, float, double 등이 포함됩니다.
  • 관례적으로, C 변수는 해당 범위의 시작(예: { } 블록 상단)에서 선언하며, 해당 범위 내의 다른 C 문장보다 먼저 선언해야 합니다.
{
    /* 1. 이 블록 내에서 사용할 변수를 블록 상단에 선언합니다. */

    int x; // x를 정수형(int) 변수로 선언하고 공간을 할당
    int i, j, k;  // 동일한 타입의 여러 변수를 한 번에 선언 가능

    char letter;  // char는 단일 바이트 정수값을 저장
                  // 주로 ASCII 문자 값을 저장하는 데 사용됨
                  // (문자의 ASCII 숫자 인코딩 값)
                  // C에서 char는 문자열(string)과 다른 타입임

    float winpct; // winpct를 실수형(float)으로 선언
    double pi;    // double은 float보다 더 정밀함

    /* 2. 변수를 정의한 후 C 문장에서 사용할 수 있습니다. */

    x = 7;        // x에 7 저장 (사용 전에 초기화 필요)
    k = x + 2;    // x 값을 표현식에 사용

    letter = 'A';        // 단일 문자 값은 작은따옴표(')로 표시
    letter = letter + 1; // letter에 'B' 저장 ('A'의 ASCII 값 + 1)

    pi = 3.1415926;

    winpct = 11 / 2.0; // winpct는 5.5 저장 (실수형 나눗셈)
    j = 11 / 2;        // j는 5 저장 (정수 나눗셈은 소수점 이하 버림)
    x = k % 2;         // %는 C의 나머지 연산자(mod), x는 9 mod 2 (1)
}

중요 사항

  • 세미콜론(;):
    • C 문장은 세미콜론으로 구분되며, 줄바꿈으로 구분되지 않습니다.
    • 세미콜론을 빠뜨리면 오류가 발생할 수 있으며, 컴파일러(gcc)는 종종 잘못된 줄에 오류를 표시합니다.

1.1.3. C Types

C supports a small set of built-in data types, and it provides a few ways in which programmers can construct basic collections of types (arrays and structs). From these basic building blocks, a C programmer can build complex data structures.

C defines a set of basic types for storing numeric values. Here are some examples of numeric literal values of different C types:

8     // the int value 8
3.4   // the double value 3.4
'h'   // the char value 'h' (its value is 104, the ASCII value of h)

The C char type stores a numeric value. However, it’s often used by programmers to store the value of an ASCII character. A character literal value is specified in C as a single character between single quotes.

C doesn’t support a string type, but programmers can create strings from the char type and C’s support for constructing arrays of values, which we discuss in later sections. C does, however, support a way of expressing string literal values in programs: a string literal is any sequence of characters between double quotes. C programmers often pass string literals as the format string argument to printf:

printf("this is a C string\n");

Python supports strings, but it doesn’t have a char type. In C, a string and a char are two very different types, and they evaluate differently. This difference is illustrated by contrasting a C string literal that contains one character with a C char literal. For example:

'h'  // this is a char literal value   (its value is 104, the ASCII value of h)
"h"  // this is a string literal value (its value is NOT 104, it is not a char)

We discuss C strings and char variables in more detail in the Strings section later in this chapter. Here, we’ll mainly focus on C’s numeric types.

C Numeric Types

C supports several different types for storing numeric values. The types differ in the format of the numeric values they represent. For example, the float and double types can represent real values, int represents signed integer values, and unsigned int represents unsigned integer values. Real values are positive or negative values with a decimal point, such as -1.23 or 0.0056. Signed integers store positive, negative, or zero integer values, such as -333, 0, or 3456. Unsigned integers store strictly nonnegative integer values, such as 0 or 1234.

C’s numeric types also differ in the range and precision of the values they can represent. The range or precision of a value depends on the number of bytes associated with its type. Types with more bytes can represent a larger range of values (for integer types), or higher-precision values (for real types), than types with fewer bytes.

Table 2 shows the number of storage bytes, the kind of numeric values stored, and how to declare a variable for a variety of common C numeric types (note that these are typical sizes — the exact number of bytes depends on the hardware architecture).

Table 2. C Numeric TypesType nameUsual sizeValues storedHow to declare
char 1 byte integers char x;
short 2 bytes signed integers short x;
int 4 bytes signed integers int x;
long 4 or 8 bytes signed integers long x;
long long 8 bytes signed integers long long x;
float 4 bytes signed real numbers float x;
double 8 bytes signed real numbers double x;

C also provides unsigned versions of the integer numeric types (char, short, int, long, and long long). To declare a variable as unsigned, add the keyword unsigned before the type name. For example:

int x;           // x is a signed int variable
unsigned int y;  // y is an unsigned int variable

The C standard doesn’t specify whether the char type is signed or unsigned. As a result, some implementations might implement char as signed integer values and others as unsigned. It’s good programming practice to explicitly declare unsigned char if you want to use the unsigned version of a char variable.

The exact number of bytes for each of the C types might vary from one architecture to the next. The sizes in Table 2 are minimum (and common) sizes for each type. You can print the exact size on a given machine using C’s sizeof operator, which takes the name of a type as an argument and evaluates to the number of bytes used to store that type. For example:

printf("number of bytes in an int: %lu\n", sizeof(int));
printf("number of bytes in a short: %lu\n", sizeof(short));

The sizeof operator evaluates to an unsigned long value, so in the call to printf, use the placeholder %lu to print its value. On most architectures the output of these statements will be:

number of bytes in an int: 4
number of bytes in a short: 2

Arithmetic Operators

Arithmetic operators combine values of numeric types. The resulting type of the operation is based on the types of the operands. For example, if two int values are combined with an arithmetic operator, the resulting type is also an integer.

C performs automatic type conversion when an operator combines operands of two different types. For example, if an int operand is combined with a float operand, the integer operand is first converted to its floating-point equivalent before the operator is applied, and the type of the operation’s result is float.

The following arithmetic operators can be used on most numeric type operands:

  • add (+) and subtract (-)
  • multiply (*), divide (/), and mod (%):

    If both operands are int types, the divide operator (/) performs integer division (the resulting value is an int, truncating anything beyond the decimal point from the division operation). For example 8/3 evaluates to 2.

    If one or both of the operands are float (or double), / performs real division and evaluates to a float (or double) result. For example, 8 / 3.0 evaluates to approximately 2.666667.

  • The mod operator (%) can only take integer-type operands (int, unsigned int, short, and so on).
  • assignment (=):
  • variable = value of expression;  // e.g., x = 3 + 4;
  • assignment with update (+=, -=, *=, /=, and %=):
  • variable op= expression;  // e.g., x += 3; is shorthand for x = x + 3;
  • increment (++) and decrement (--):
  • variable++;  // e.g., x++; assigns to x the value of x + 1
 
Pre- vs. Post-increment
The operators ++variable and variable++ are both valid, but they’re evaluated slightly differently:
  • ++x: increment x first, then use its value.
  • x++: use `x’s value first, then increment it.
In many cases, it doesn’t matter which you use because the value of the incremented or decremented variable isn’t being used in the statement. For example, these two statements are equivalent (although the first is the most commonly used syntax for this statement):
 
In some cases, the context affects the outcome (when the value of the incremented or decremented variable is being used in the statement). For example:
 
Code like the preceding example that uses an arithmetic expression with an increment operator is often hard to read, and it’s easy to get wrong. As a result, it’s generally best to avoid writing code like this; instead, write separate statements for exactly the order you want. For example, if you want to first increment x and then assign x + 1 to y, just write it as two separate statements.
Instead of writing this:
 
write it as two separate statements:
 

1.1.3. C 데이터 타입

C는 소수의 기본 데이터 타입과 배열 및 구조체 같은 기본 컬렉션 타입을 제공합니다. 이를 통해 복잡한 데이터 구조를 구성할 수 있습니다.

C 숫자형

C는 다양한 숫자 값을 저장하기 위한 여러 타입을 지원하며, 각 타입은 표현 가능한 값의 범위와 정밀도가 다릅니다.

기본 숫자형 예시

  • 8: 정수형(int) 값
  • 3.4: 실수형(double) 값
  • 'h': 문자형(char) 값 (ASCII 값은 104)

부호 없는(unsigned) 숫자형

  • 모든 정수형(char, short, int, long, long long)은 부호 없는 버전을 지원합니다.
  • 예:
int x;           // 부호 있는 int 변수
unsigned int y;  // 부호 없는 int 변수

타입 크기 확인

C의 sizeof 연산자를 사용하여 특정 타입이 사용하는 바이트 수를 확인할 수 있습니다:

printf("int 크기: %lu 바이트\n", sizeof(int));
printf("short 크기: %lu 바이트\n", sizeof(short));

# 출력 예시
int 크기: 4 바이트
short 크기: 2 바이트

산술 연산자

C는 대부분의 숫자형에 대해 다음 산술 연산자를 제공합니다:

  • 덧셈(+) 및 뺄셈(-)
  • 곱셈(*), 나눗셈(/), 나머지(%)
    • %: 정수형에만 사용 가능
    • /: 피연산자가 모두 정수면 정수 나눗셈(소수점 이하 버림), 하나라도 실수면 실수 나눗셈

증가/감소 연산자

  • 증가(++) 및 감소(--) 연산자는 전치(prefix)와 후치(postfix) 방식으로 사용 가능:
    • 전치(++x): 먼저 증가 후 사용
    • 후치(x++): 먼저 사용 후 증가
x = 6;
y = ++x + 2;  // y = 9 (x를 먼저 증가 -> x + 2 계산)
x = 6;
y = x++ + 2;  // y = 8 (x + 2 계산 -> 이후 x 증가)

 

이처럼 증감 연산자를 포함한 표현식은 읽기 어렵고 실수가 발생하기 쉬우므로, 명확성을 위해 별도의 문장으로 작성하는 것이 좋습니다:

x++;
y = x + 1;

 

https://diveintosystems.org/book/C1-C_intro/getting_started.html

 

Dive Into Systems

Python is an interpreted programming language, which means that another program, the Python interpreter, runs Python programs: the Python interpreter acts like a virtual machine on which Python programs are run. To run a Python program, the program source

diveintosystems.org

 

'컴퓨터 > deep dive into systems' 카테고리의 다른 글

0. Introduction  (0) 2025.01.26