https://kthdev.tistory.com/40 (작성중)
smily project 를 작성하고 컴파일까지 완료, 정상작동 확인을 했고 제출까지 했다.
[chat gpt는 제출하는 과제에는 사용하지 않았습니다.]
아무리 찾아봐도 나는 분명 helpers.c를 수정했는데, 실행은 colorize를 했다.
colorize는 helpers.h를 가지고 있지만 helpers.c는 언급하지 않고,
helpers.c는 makefile이라는 파일에서 언급이 되어있었다.
makefile이라는게 뭔지 처음봐서, chat gpt에게 함 물어봤다.
파일을 올릴수가 없어서, 내용을 구분해서 다 알려주고 질문했다.
내용이 너무 길어서 질문을 접어둔다.
## content of makefile ##
colorize:
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -o colorize colorize.c helpers.c
## content of colorize.c ##
#include <stdio.h>
#include <stdlib.h>
#include "helpers.h"
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 3)
{
printf("Usage: colorize infile outfile\n");
return 1;
}
// remember filenames
char *infile = argv[1];
char *outfile = argv[2];
// open input file
FILE *inptr = fopen(infile, "r");
if (inptr == NULL)
{
printf("Could not open %s.\n", infile);
return 4;
}
// open output file
FILE *outptr = fopen(outfile, "w");
if (outptr == NULL)
{
fclose(inptr);
printf("Could not create %s.\n", outfile);
return 5;
}
// read infile's BITMAPFILEHEADER
BITMAPFILEHEADER bf;
fread(&bf, sizeof(BITMAPFILEHEADER), 1, inptr);
// read infile's BITMAPINFOHEADER
BITMAPINFOHEADER bi;
fread(&bi, sizeof(BITMAPINFOHEADER), 1, inptr);
// ensure infile is (likely) a 24-bit uncompressed BMP 4.0
if (bf.bfType != 0x4d42 || bf.bfOffBits != 54 || bi.biSize != 40 ||
bi.biBitCount != 24 || bi.biCompression != 0)
{
fclose(outptr);
fclose(inptr);
printf("Unsupported file format.\n");
return 6;
}
int height = abs(bi.biHeight);
int width = bi.biWidth;
// allocate memory for image
//RGBTRIPLE 요소가 width개 있는 배열을 가르킬수 있는 포인터 선언.
//그리고 width개의 배열을 가진 image 포인터배열을
//height 갯수만큼 메모리에 할당함으로서, 2차원 배열이 된다.
//접근할때는 image[height][width] 형식으로 접근 가능하다.
RGBTRIPLE (*image)[width] = calloc(height, width * sizeof(RGBTRIPLE));
if (image == NULL)
{
printf("Not enough memory to store image.\n");
fclose(outptr);
fclose(inptr);
return 7;
}
// determine padding for scanlines
int padding = (4 - (width * sizeof(RGBTRIPLE)) % 4) % 4;
// iterate over infile's scanlines
for (int i = 0; i < height; i++)
{
// read row into pixel array
//fread 를 통해 image[i] 에다가 RGBTRIPLE 크기의 데이터를 width갯수만큼
//(아까 width 갯수만큼의 크기를 가진 배열을 가르키는 포인터로 선언함)
//또한 그 배열포인터를 또 height만큼의 배열로 메모리를 동적할당하였음.
//inptr에서 가져온 값을 입력함.
fread(image[i], sizeof(RGBTRIPLE), width, inptr);
// skip over padding
//이 padding은 bmp파일의 특성으로,
//각 행의 픽셀이 4바이트 단위로 끝나야 읽어올 수 있으므로,
// padding을 넣어줘야 한다. 이는 bmp 알고리즘 특성이다.
fseek(inptr, padding, SEEK_CUR);
}
//이제 image에 값을 다 불러와서 처리만 하면 된다.
colorize(height, width, image);
// write outfile's BITMAPFILEHEADER 파일헤더 입력
fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, outptr);
// write outfile's BITMAPINFOHEADER 인포헤더 입력
fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, outptr);
// write new pixels to outfile
//이 루프를 돌리는 가장 큰 이유는
//각 열 마다 패딩을 넣어줘야 하기 때문이다.
for (int i = 0; i < height; i++)
{
// write row to outfile
fwrite(image[i], sizeof(RGBTRIPLE), width, outptr);
//이렇게 가능한 아유는
//이미지 파일, bmp는 좌우 가로 데이터 사이즈가 똑같으므로
//각 열의 padding 사이즈는 모든 열에서 동일하다.
// write padding at end of row
for (int k = 0; k < padding; k++)
{
fputc(0x00, outptr);
}
}
// free memory for image
free(image);
// close infile
fclose(inptr);
// close outfile
fclose(outptr);
return 0;
}
##content of helpers.c ##
#include "helpers.h"
void colorize(int height, int width, RGBTRIPLE image[height][width])
{
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
if (
image[i][j].rgbtBlue == 0X00 &&
image[i][j].rgbtGreen == 0x00 &&
image[i][j].rgbtRed == 0x00
)
{
image[i][j].rgbtBlue = 0x00;
image[i][j].rgbtGreen = 0x00;
image[i][j].rgbtRed = 0xAA;
};
};
};
// Change all black pixels to a color of your choosing
}
## content of helpers.h ##
#include "bmp.h"
// colorize image
void colorize(int height, int width, RGBTRIPLE image[height][width]);
## content of bmp.h ##
// BMP-related data types based on Microsoft's own
#include <stdint.h>
/**
* Common Data Types
*
* The data types in this section are essentially aliases for C/C++
* primitive data types.
*
* Adapted from http://msdn.microsoft.com/en-us/library/cc230309.aspx.
* See http://en.wikipedia.org/wiki/Stdint.h for more on stdint.h.
*/
typedef uint8_t BYTE;
typedef uint32_t DWORD;
typedef int32_t LONG;
typedef uint16_t WORD;
/**
* BITMAPFILEHEADER
*
* The BITMAPFILEHEADER structure contains information about the type, size,
* and layout of a file that contains a DIB [device-independent bitmap].
*
* Adapted from http://msdn.microsoft.com/en-us/library/dd183374(VS.85).aspx.
*/
typedef struct
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} __attribute__((__packed__))
BITMAPFILEHEADER;
/**
* BITMAPINFOHEADER
*
* The BITMAPINFOHEADER structure contains information about the
* dimensions and color format of a DIB [device-independent bitmap].
*
* Adapted from http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx.
*/
typedef struct
{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} __attribute__((__packed__))
BITMAPINFOHEADER;
/**
* RGBTRIPLE
*
* This structure describes a color consisting of relative intensities of
* red, green, and blue.
*
* Adapted from http://msdn.microsoft.com/en-us/library/aa922590.aspx.
*/
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
--------------
all files above are located in same folder.
how can colorize access helpers.c?
colorize.c is mentioned only on makefile,
but there are no mention about accessing makefile at all.
답변
In the given code, the colorize function in helpers.c can be accessed by the colorize function in colorize.c because both files are part of the same project or program.
The #include "helpers.h" statement in colorize.c includes the header file helpers.h, which contains the function prototype for the colorize function. This allows the colorize function in colorize.c to call the colorize function defined in helpers.c and use its implementation.
The makefile is used as a build configuration file to compile the project. It specifies the necessary compilation commands and dependencies to build the executable. In this case, the makefile compiles the colorize program by linking colorize.c and helpers.c together, which allows the functions defined in helpers.c to be accessed by colorize.c.
So, even though there is no direct mention of accessing helpers.c in the code, the inclusion of the header files and the compilation process through the makefile enables the access and linkage between the source files in the project.
추가질문
질문 : Is makefile has same style for every compiler? How can i use makefile? Is there some standard rule for that?
답변
Makefile is a build automation tool commonly used in software development projects. While the syntax and conventions in Makefile can vary depending on the specific build system and the preferences of the project, there are some common principles and rules that are typically followed.
Here are some key points about Makefile:
1. Targets: Makefile consists of rules that define targets, which are the final outputs or intermediate steps in the build process. Each rule specifies the dependencies required to build the target and the commands to execute.
2. Dependencies: The dependencies are the files or other targets that are needed to build a particular target. Makefile uses dependency tracking to determine which targets need to be rebuilt based on changes in their dependencies.
3. Commands: Makefile rules include the shell commands that are executed to build the target. These commands are typically indented with a tab character.
4. Variables: Makefile allows you to define variables to store values that can be reused throughout the file. Variables are often used to store compiler flags, file names, or any other reusable values.
5. Automatic Variables: Makefile provides a set of predefined variables that can be used in rules. These variables represent information about the current rule being executed, such as the target name or the source file name.
6. Phony Targets: Phony targets are targets that do not represent actual files but are used to execute a sequence of commands. These targets are declared with the .PHONY directive.
To use a Makefile, you typically navigate to the directory containing the Makefile in the command-line interface and run the make command. The make command reads the Makefile and executes the specified targets and their associated rules.
It's important to note that Makefile syntax can vary slightly between different build systems and platforms. However, the basic concepts and principles remain the same. The specific details and conventions used in a Makefile can depend on the programming language, build tools, and project requirements.
If you are working with a particular build system or project, it's recommended to consult the documentation or conventions established by the project to ensure compatibility and adherence to the specific Makefile style used.
하.. 영어를 읽는게 에너지가 너무 많이 들어서, 마침 DeepL 한글이 오픈했길래 번역을 돌렸다.
첫번째 질문에 대한 답변 :
주어진 코드에서, 두 파일 모두 동일한 프로젝트 또는 프로그램의 일부이기 때문에 helpers.c의 colorize 함수는 colorize.c의 colorize 함수에 액세스할 수 있습니다.
colorize.c의 #include "helpers.h" 문에는 colorize 함수에 대한 함수 프로토타입이 포함된 헤더 파일 helpers.h가 포함되어 있습니다. 이를 통해 colorize.c의 colorize 함수는 helpers.c에 정의된 colorize 함수를 호출하고 그 구현을 사용할 수 있습니다.
메이크파일은 프로젝트를 컴파일하기 위한 빌드 구성 파일로 사용됩니다. 이 파일은 실행 파일을 빌드하는 데 필요한 컴파일 명령과 종속성을 지정합니다. 이 경우 메이크파일은 colorize.c와 helpers.c를 함께 링크하여 colorize 프로그램을 컴파일하므로 helpers.c에 정의된 함수에 colorize.c에서 액세스할 수 있습니다.
따라서 코드에 helpers.c에 대한 직접적인 액세스 언급이 없더라도 헤더 파일을 포함하고 메이크파일을 통한 컴파일 프로세스를 통해 프로젝트 내 소스 파일 간의 액세스 및 연결이 가능합니다.
두번째 질문에 대한 답변 :
메이크파일은 소프트웨어 개발 프로젝트에서 일반적으로 사용되는 빌드 자동화 도구입니다. 메이크파일의 구문과 규칙은 특정 빌드 시스템과 프로젝트의 기본 설정에 따라 달라질 수 있지만 일반적으로 따르는 몇 가지 일반적인 원칙과 규칙이 있습니다.
다음은 메이크파일에 대한 몇 가지 핵심 사항입니다:
1. 타깃: 메이크파일은 빌드 프로세스의 최종 결과물 또는 중간 단계인 타깃을 정의하는 규칙으로 구성됩니다. 각 규칙은 타깃을 빌드하는 데 필요한 종속성과 실행할 명령을 지정합니다.
2. 종속성: 종속성은 특정 대상을 빌드하는 데 필요한 파일 또는 기타 대상입니다. 메이크파일은 종속성 추적을 사용하여 종속성 변경에 따라 다시 빌드해야 하는 대상을 결정합니다.
3. 명령: 메이크파일 규칙에는 대상을 빌드하기 위해 실행되는 셸 명령이 포함됩니다. 이러한 명령은 일반적으로 탭 문자로 들여쓰기됩니다.
4. 변수: 메이크파일을 사용하면 파일 전체에서 재사용할 수 있는 값을 저장하는 변수를 정의할 수 있습니다. 변수는 컴파일러 플래그, 파일 이름 또는 기타 재사용 가능한 값을 저장하는 데 자주 사용됩니다.
5. 자동 변수: 메이크파일은 규칙에 사용할 수 있는 미리 정의된 변수 집합을 제공합니다. 이러한 변수는 대상 이름 또는 소스 파일 이름과 같이 현재 실행 중인 규칙에 대한 정보를 나타냅니다.
6. 가짜 대상: 가짜 타깃은 실제 파일을 나타내지는 않지만 일련의 명령을 실행하는 데 사용되는 타깃입니다. 이러한 대상은 .PHONY 지시어로 선언됩니다.
메이크파일을 사용하려면 일반적으로 명령줄 인터페이스에서 메이크파일이 포함된 디렉토리로 이동하여 make 명령을 실행합니다. make 명령은 메이크파일을 읽고 지정된 대상과 관련 규칙을 실행합니다.
메이크파일 구문은 빌드 시스템과 플랫폼에 따라 약간씩 다를 수 있다는 점에 유의해야 합니다. 그러나 기본 개념과 원칙은 동일하게 유지됩니다. 메이크파일에 사용되는 구체적인 세부 사항과 규칙은 프로그래밍 언어, 빌드 도구 및 프로젝트 요구 사항에 따라 달라질 수 있습니다.
특정 빌드 시스템 또는 프로젝트로 작업하는 경우 프로젝트에서 설정한 문서 또는 규칙을 참조하여 호환성을 확인하고 사용되는 특정 메이크파일 스타일을 준수하는 것이 좋습니다.
Translated with www.DeepL.com/Translator (free version)
[잠깐 나갔다와야해서, 여기 올려두고 오늘 저녁에 다시 정리하겠습니다. ]