C언어의 프로그래밍언어론적 측면에 관해서

canuyes의 이미지

과제를 하다가 궁금점이 생겨 질문올립니다.

#include <stdio.h>
 
void main() {
 
     char ch = 'a';
     printf("%d", ch);
 
}

위 프로그램은 wrong program 이지만, 컴파일도 되고 실행도 됩니다.
이렇게 C를 설계한 이유를 프로그래밍 언어론 적 측면에서 기술하려합니다.

생각해 본 바로는

1. C는 효율성을 위해 type check를 수행하지 않는다.
2. C는 문자도 내부적으로는 정수로 취급하여 다루게 된다.

등이 있습니다.

하지만 저 둘이 과연 프로그래밍 언어론 적 측면에서의 접근이 맞는 것인지,
만약에 맞다면 어떻게 풀어내야할지가 궁금합니다.

책도 찾아보고 여러 웹사이트도 돌아다녀 봤지만 질문이 모호한지라 만족할 만한 답을 얻지 못해 질문드립니다.

yukariko의 이미지

printf 는 내부가 가변인자로 받아오게끔 구현되었기 때문에
타입체크를 하지 않습니다.
할 수 없다는게 맞는 표현이려나요?

그저 맨 첫 인자를 가지고 이것이 무슨 타입인지를 결정하는것이죠.
printf의 케이스를 가지고 프로그래밍 언어론적 측면으로 고려하는게 맞는걸까요?
접근해보자면 template가 지원되지 않는다는점?

klyx의 이미지

> 위 프로그램은 wrong program 이지만, 컴파일도 되고 실행도 됩니다.

틀리지 않은 프로그램이고, 잘 정의된 작동이 보장된 코드입니다.

> 1. C는 효율성을 위해 type check를 수행하지 않는다.

컴파일 오류(경고)를 내뿜는 타입 체크는 컴파일타임에 하기 때문에 효율성과는 관계가 없습니다.

> 2. C는 문자도 내부적으로는 정수로 취급하여 다루게 된다.

char는 원래 정수입니다.

printf의 구현을 보지 않고 이걸로 C언어의 '프로그래밍 언어론'이라는 걸 논하기엔 무리가 있습니다.
가변 인자 함수가 어떻게 구현되는지 부터 찾아보시는게 좋을 듯합니다.

DarkSide의 이미지

위 프로그램은 문자의 아스키 코드를 알아 보기 위한 정상적인 프로그램입니다.
1. 위 프로그램에서도 type check는 수행된 것이며, 문자에서 정수로의 변환은 안전한 타입 변환임.
2. C 뿐만 아니라 문자를 내부적으로 숫자 아닌 다른 무엇으로 표현하는 것은 불가능함.

익명 사용자의 이미지

printf의 argument로 1byte 짜리 하나가 넘어갔고
printf의 내부에서는 4byte를 읽으려고 할 텐데 어찌 정상적인 프로그램이 될 수 있나요?

byte align 같은 문제로 인해 1byte이후 나머지 3byte는 0으로 채워진다 라는 보장이 없으면
이상한 쓰레기 값을 출력하는 코드일텐데요.

klyx의 이미지

추측하지 마시고 가변 인자 함수가 어떻게 동작하는지 부터 찾아보세요.

익명 사용자의 이미지

뭔가 착각하시는거 같은데 char타입을 넘겼다고 해서 정말로 1바이트가 넘어갈 것 같은가요?
또는 char 변수 하나를 정의했다고 정말 스택영역을 1바이트만 더 늘려서 잡을까요?

프로그램은 기본적으로 word 단위로 처리를 하기 때문에, x86 기준으로 push/pop 명령은
항상 word 단위로 처리됩니다. 그러니 윗 분이 말씀하신 것 같은 상황은 전혀 벌어지지 않습니다.
(char a = 0x22; 이고 &a = 0x80000000 이라고 할 때 0x80000001 부터는 무슨 쓰레기값이
들어있는 게 아닙니다. 0x22 는 결국 4바이트 정수 0x00000022 로 내부적으로 취급됩니다.)

그리고 저건 C의 설계가 문제가 아니라, printf 함수의 구현 문제이며 가변인자의 문제입니다.
가변 인자에서는 원래 type check 를 하지 못하고, 어떤 타입이 넘어왔는지 알 수 있는 방법은 없습니다.
또한 문자에서 정수 변환 된 것이 아닙니다. printf 뒤에 그 어떤 타입을 넘긴다고 해도 컴파일 오류는 나지 않습니다.

%d 나 %c 등의 포맷 스트링은 내부적으로 printf 에서 핸들링하는 것이지 이걸 컴파일 타임에
타입을 체크하기 위한 용도로 쓰는 게 아니고, 또한 이건 타입을 알기 위한 목적으로 쓰는 것이 아니라
넘어온 인자에 대한 출력 타입을 정하는 목적으로 사용하는 것입니다.

익명 사용자의 이미지

많은 CPU 아키텍처가 4byte / 8byte 단위를 기본으로 하기 때문에
char 타입을 선언해 사용하더라도 4byte 이상의 메모리를 쓰는 경우가 많지요.
하지만 그건 현재 사용하고 있는 CPU 아키텍처에 따른 부수적인 효과지
C언어의 스펙에 "char변수의 argument를 넘길시 stack은 4byte 늘려서 잡아야 한다"라고 명시되어 있을까요?
대부분의 경우에 잘 동작한다고 해서 그게 100%를 보장하는 진리가 되지는 않습니다.

klyx의 이미지

이게 적법한건 플랫폼에 의존하는 것이 아니라 표준에 의해서 보장된 것입니다.

익명 사용자의 이미지

void main 빼고는 표준에 의해 문제없는 코드가 맞습니다.
가변 인자 진급default argument promotion이라고 찾아보세요.

C언어는 이론적으로나 언어적으로 아름다운 모습은 아닌데.
이는 효율성, 전통, 호환성, 이식성, 기타 이유들이
이런 저런 역사적 과정을 거쳐 타협해간 결과입니다.

가변인자 함수는 원래는 매크로적인 트릭이었다가
표준화 과정에서 정식 문법으로 흡수된 특징입니다.
원래는 윗분이 예상한 대로 플랫폼 의존적인 테크닉 이었겠지만
지금은 아닙니다.

익명 사용자의 이미지

가변 인자 진급이 아니라 기본 인자 진급입니다.
영어로는 똑바로 썼는데 한국어로는 그만 실수했군요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.