반응형

요즘 기본기가 중요함을 느끼고 C를 공부하고 있습니다. 

 

 

1. 구조체 단순히접근

#include <stdio.h>

//Struct packet 선언
typedef struct packet
{
	int data0;
	int data1;
	int data2;

}Packet;

int main()
{
	Packet p;  //Struct Packet 정의

	p.data0 = 0;
	p.data1 = 1;
	p.data2 = 2;

	printf("%d %d %d ", p.data0, p.data1, p.data2);
	return 0;
}

 

 

 

 

 

2. 구조체 포인터로 접근

#include <stdio.h>


// Struct packet 선언
typedef struct packet
{
	int data0;
	int data1;
	int data2;

}Packet;



int main()
{
	Packet p;  // Struct Packet 정의
	Packet* p_pointer;  // Packet에 대한 Pointer 선언 
	p_pointer = &p;  // Pointer 정의 

	p_pointer->data0 = 0;
	p_pointer->data1 = 1;
	p_pointer->data2 = 2;

	printf("%d %d %d ", p.data0, p.data1, p.data2);
	return 0;
}

 

 

 

 

 

3. Struct 최적화 (Padding bit)

#include <stdio.h>


// Struct packet 선언
typedef struct packet
{
	char data0;
	char data1;
	int data2;

}Packet;



int main()
{
	Packet p;  // Struct Packet 정의

	printf("%d", sizeof(p));

	return 0;
}

 

과연 위 구제체는 몇 비트인가?

 

6바이트라고 생각할 수 있지만, 8바이트

 

이유 : 구조체는 가장 큰 변수만큼 증가하기 때문이다. 

 

그렇다면 둘의 순서가 바뀌면 어떻게 되는가?

 

#include <stdio.h>


// Struct packet 선언
typedef struct packet
{
	int data0;
	char data1;
	char data2;
	

}Packet;



int main()
{
	Packet p;  // Struct Packet 정의

	printf("%d", sizeof(p));

	return 0;
}

 

똑같이 8바이트이다.

 

그렇다면 이런 구조체일 때는 몇 바이트인가?

 

#include <stdio.h>


// Struct packet 선언
typedef struct packet
{
	char data0;
	int data1;
	char data2;
	

}Packet;



int main()
{
	Packet p;  // Struct Packet 정의

	printf("%d", sizeof(p));

	return 0;
}

위 구조체는 12bytes이다.

 

극한의 메모리 낭비를 일으킨다. 

 

BLE 통신을 하게 되었는데, 통신에서는 이런 구조체와 공용체가 굉장히 중요하다. 

728x90
반응형
반응형

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>


#pragma warning(disable:4996)
#define _CRT_SECURE_NO_WARNINGS

typedef uint8_t  BYTE;
typedef uint32_t DWORD;
typedef int32_t  LONG;
typedef uint16_t WORD;


/*********************************************************STRUCTS***********************************************************/
#pragma pack(push, 1)
typedef struct tagBITMAPFILEHEADER
{
WORD bfType;  //specifies the file type
DWORD bfSize;  //specifies the size in bytes of the bitmap file
WORD bfReserved1;  //reserved; must be 0
WORD bfReserved2;  //reserved; must be 0
DWORD bfOffBits;  //species the offset in bytes from the bitmapfileheader to the bitmap bits
}BITMAPFILEHEADER;


typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;  //specifies the number of bytes required by the struct
LONG biWidth;  //specifies width in pixels
LONG biHeight;  //species height in pixels
WORD biPlanes; //specifies the number of color planes, must be 1
WORD biBitCount; //specifies the number of bit per pixel
DWORD biCompression;//specifies the type of compression
DWORD biSizeImage;  //size of image in bytes
LONG biXPelsPerMeter;  //number of pixels per meter in x axis
LONG biYPelsPerMeter;  //number of pixels per meter in y axis
DWORD biClrUsed;  //number of colors used by the bitmap
DWORD biClrImportant;  //number of colors that are important
}BITMAPINFOHEADER;

typedef struct
{
BYTE  rgbtBlue;
BYTE  rgbtGreen;
BYTE  rgbtRed;
}RGBTRIPLE;

typedef struct
{
BYTE hslHue;
BYTE hslSaturation;
BYTE hslLightness;
}HSL;
#pragma pack(pop)
/*********************************************************STRUCTS***********************************************************/

#define filterWidth 3
#define filterHeight 3

void Filters(int biHeight, int biWidth, RGBTRIPLE** triple);
int CopyBitmapFile(char* filename, BITMAPINFOHEADER* bitmapInfoHeader, char* copy_filename);

int main()
{
char image[80], image_copy[80];
printf("원본 이미지 파일 : ");
scanf("%s", image);

printf("편집 이미지 파일 : ");
scanf("%s", image_copy);


BITMAPINFOHEADER bitmapInfoHeader;
memset(&bitmapInfoHeader, 0, sizeof(BITMAPINFOHEADER));
CopyBitmapFile(image, &bitmapInfoHeader, image_copy);

}


int CopyBitmapFile(char* filename, BITMAPINFOHEADER* bitmapInfoHeader, char* copy_filename)
{
int i, j, k;
FILE* filePtr; 
BITMAPFILEHEADER bitmapFileHeader; 
memset(&bitmapFileHeader, 0, sizeof(BITMAPFILEHEADER));

filePtr = fopen(filename, "rb");
if (filePtr == NULL)
return 1;

FILE* outptr = fopen(copy_filename, "wb");
if (outptr == NULL)
{
fclose(filePtr);
fprintf(stderr, "Could not create %s.\n", copy_filename);
return 2;
}


fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);

if (bitmapFileHeader.bfType != 0x4D42)
{
printf("이미지 파일 찾을 수 없엉");
fclose(filePtr);
fclose(outptr);
return 3;
}


fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);


fwrite(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, outptr);

fwrite(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, outptr);

int padding = (4 - (bitmapInfoHeader->biWidth * sizeof(RGBTRIPLE)) % 4) % 4;

int biHeight = abs(bitmapInfoHeader->biHeight);
int biWidth = bitmapInfoHeader->biWidth;

RGBTRIPLE** triple;
triple = (RGBTRIPLE**)malloc(sizeof(RGBTRIPLE*) * biHeight);
int ii;
for (ii = 0; ii < biHeight; ii++)
{
triple[ii] = (RGBTRIPLE*)malloc(sizeof(RGBTRIPLE) * biWidth);
}


for (i = 0; i < biHeight; i++)
{
for (j = 0; j < biWidth; j++)
{
fread(&triple[i][j], sizeof(RGBTRIPLE), 1, filePtr);
}
}



for (i = 0; i < biHeight; i++)
{
for (j = 0; j < biWidth; j++)
{
// brighter image
int x, y, z;
x = triple[i][j].rgbtBlue  + 75;
y = triple[i][j].rgbtGreen + 75;
z = triple[i][j].rgbtRed + 75;
triple[i][j].rgbtBlue = ((x > 255) ? 255 : x);
triple[i][j].rgbtGreen = ((y > 255) ? 255 : y);
triple[i][j].rgbtRed = ((z > 255) ? 255 : z);
}
}

for (i = 0; i < biHeight; i++)
{
for (j = 0; j < biWidth; j++)
{

fwrite(&triple[i][j], sizeof(RGBTRIPLE), 1, outptr);
}

fseek(filePtr, padding, SEEK_CUR);

for (k = 0; k < padding; k++)
{
fputc(0x00, outptr);
}
}

fclose(filePtr);
fclose(outptr);

for(int p = 0; p < biHeight; p++ )
{
free(triple[p]);
}
free(triple);

return 0;
}

728x90
반응형
반응형

예제2.cpp
0.00MB

안녕하세요. 2차원 배열 동적할당하기 두 번째글입니다.

 

1편에서 처럼 2차원 배열을 표현하게 되면 column끼리는 바이트가 순차적입니다.

 

하지만 row끼리는 다른 메모리 공간에서 할당받게 됩니다. 

 

메모리 공간이 순차적이지 않기 때문에 배열에 접근할 때마다 불필요한 동작이 생기게 됩니다. 

 

메모리 공간을 활용하기 위해 다른 방법을 사용하도록 하겠습니다.

 

그림과 같이 일차원 배열을 마치 이차원 배열처럼 표현할 수 있습니다.

일차원 배열로 이차배열만들기

 

장점 : 메모리가 1편처럼 끊어지지 않습니다.

단점 : 1. 배열을 사용할 때 인덱스가 복잡하다는 것입니다. 

      

 

int* mat;       

mat = (int*)malloc(sizeof(int) * column * row);      // 배열의 크기만큼 메모리 할당

 

    for (int i = 0; i < column; i++)

    {

        for (int j = 0; j < row; j++)

        {

            mat[(column * i) + j] = (i * column) + j;      //(i열 ...) + j행

        }

    }

 

메모리를 한 번 할당했으니 메모리 해제도 한 번만 해줍니다.

free(mat);

 

그렇다면 이제 주소를 한 번 찍어보도록 하겠습니다.

3x3배열
5x5배열

728x90
반응형
반응형

1_1.cpp
0.00MB

c언어에서 2차원배열을 만드는 방법은 이와 같습니다. 

arr[3][3] = {0, };

그러면 3X3 2차원 배열이 생성됩니다.

하지만 가로의 크기와 세로의 크기를 컴파일 이전 시간에 미리 정해줘야 합니다.

즉, 가로 안에 상수가 들어가야합니다. 

만약 실행 도중에 사용자가 원하는 크기만큼의 배열을 만들고 싶으면 어떻게 해야할까요?

2차행렬 동적할당

아마 가장 보편적으로 알려져 있는 방법입니다.

 

scanf("%d", column);

scanf("%d", row);

 

int **arr;
arr = (int**) malloc ( sizeof(int*) * column);
for(int i=0; i<column; i++){
    arr[i] = (int*) malloc ( sizeof(int) * row );
}

 

하지만 문제점이 하나 있습니다.

 

만약 주소를 찍으면 어떻게 될까요?

for(int i=0; i<column; i++){

     for(int j=0; row; j++){

          printf("%d  ", &arr[i][j]);  

      }

      printf("\n");

}

 

 

행으로는 포인터가 4바이트로 연결 되지만, 다음 열로 새로운 시작주소를  받습니다.

 arr[0][], arr[1][], arr[2][]의 값에 접근할 때마다 시작주소가 바뀌어 불필요한 동작을 일으킵니다. 

이제 다음 동적할당 예제로는 하나의 시작주소로 시작해 순차적으로 카운트되도록 만들어 보겠습니다.  

 

메모리 공간을 사용했으면 이제 해제해줍니다.

for (i = 0; i < row; i++) {

     free(arr[i]);

     }

free(arr);

728x90
반응형

+ Recent posts