콘텐츠로 바로가기

now0930 일지

이런저런 생각

  • 홈
  • 비공개
  • 강좌
  • 잔여 작업 조회
  • 위치

c 더블 포인터 이해하기.

c는 포인터가 혼란스러운데 이해했다고 믿고???? 나중에 다시 생각하려고 남긴다.

다음 코드를 만들었고 실패했다. bufToStruct를 실행할 때 포인터로 넘겼어도 buf를 받으면서 임시 공간에 변수를 만든다. 함수 실행을 끝내면서 그 공간도 날아가 도로묵 된다.

#include <stdio.h>
#include "module1.h"
int main()
{
    struct mysqlStruct oneSqlData;
    char readbuf[MAX_LEN];
    int ret;
    openfile(readbuf);
    printf("버퍼는 %s\n",readbuf);
    do{ 
        ret=bufToStruct(readbuf, &oneSqlData);
        printf("%p\n", readbuf);
        sleep(1);
    }while(ret==-1);
    //bufToStruct(readbuf, &oneSqlData);

    return 0;
}
int bufToStruct(char* buf, struct mysqlStruct *sqlData){

	//buf를 읽어 날자, 시각, 온도로 분리.
	//,로 분리되어 delimiter로 분리..
	//한번 읽을때마다 buf 한 줄 내용을 sqlData로 이동.
	//성공하면 0,
	//마지막이면 1,
	//실패하면 -1을 return.

	size_t len;
	char* temp;		//시작 위치
	len=strlen(buf);
	char tempbuf[len];		//strtok로 작업할 내용. strtok이 원래 버퍼를 수정함.
	char *year,*month, *day, *hour, *minute, *temperature;
	int year2, month2, day2, hour2, minute2, temperature2;
	//strtok이 원래 버퍼를 잘라 버려.
	//임시로 카피해서 사용.
	//원래 포인터는 토큰 크기만큼 넘김.
	strcpy(tempbuf, buf);

	//첫줄을 읽을 경우 무시할 방법 필요.
	//그냥 넣어서 에러, 정상 확인.
	temp = strtok(tempbuf, "\n");

	len=strlen(temp);
	year=strtok(temp, "-");
	//무슨 데이터인지 모르겠지만, 일단 숫자료 변경.
	year2=atoi(year);

	//buf 내용 삭제..temp 만큼.
	//buf 포인터를 temp 만큼 이동.
	for(int i=0;i<len;i++)
		buf++;

	if(year2 < 2000 || year2 > 2100)
		return -1;

	//정상대로 진행.
	sqlData->year = year2;
	printf("year2 is %d\n",year2);
	month=strtok(temp,"-");
	month=strtok(temp,"-");
	month2=atoi(month);
	sqlData->month = month2;

	
}

위 내용을 gdb로 확인해 보았다.

(gdb) run
Starting program: /home/pi/Project/cCode/module1/insertTemperature 
버퍼는 날자, 온도
2020-7-9 10:00:00, 24.5
2020-7-9 10:01:00, 24.5
2020-7-9 10:02:00, 24.5
2020-7-9 10:03:00, 24.5


Breakpoint 1, main () at main.c:11
11			ret=bufToStruct(readbuf, &oneSqlData);
(gdb) display &readbuf
1: &readbuf = (char (*)[200]) 0xbefff30c
(gdb) s
bufToStruct (
    buf=0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n", sqlData=0xbefff3d4)
    at module1.c:42
42	int bufToStruct(char* buf, struct mysqlStruct *sqlData){
(gdb) l
37	
38		// ruturn 성공.
39		return 0;
40	}
41	
42	int bufToStruct(char* buf, struct mysqlStruct *sqlData){
43	
44		//buf를 읽어 날자, 시각, 온도로 분리.
45		//,로 분리되어 delimiter로 분리..
46		//한번 읽을때마다 buf 한 줄 내용을 sqlData로 이동.
(gdb) 
47		//성공하면 0,
48		//마지막이면 1,
49		//실패하면 -1을 return.
50	
51		size_t len;
52		char* temp;		//시작 위치
53		len=strlen(buf);
54		char tempbuf[len];		//strtok로 작업할 내용. strtok이 원래 버퍼를 수정함.
55		char *year,*month, *day, *hour, *minute, *temperature;
56		int year2, month2, day2, hour2, minute2, temperature2;
(gdb) display &buf
2: &buf = (char **) 0xbefff2cc
(gdb) display buf
3: buf = 0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n"

bufToStruct로 readbuf를 전달할 때 주소를 전달하는 직접 전달하길 원했다. bufToStruct로 전달하는 0xbefff2cc는 어디에서 나왔을까? 임시 변수로 자기가 만들었다. 임시로 만든(콜 하고 없어질) 주소에 포인터 값을 넣었다. 그러니 함수 내부에서 열심히 포인터를 움직여도 메인 함수 포인터는 변하지 않았다. &buf = 0xbefff30c로 바꿔야 한다. 이중 포인터가 그 역할을 한다.

다음 그림을 참조하면 쉽게?? 이해할 수 있다. 이게 머라고 삽질하고 있는지..

#include <stdio.h>
#include "module1.h"
int main()
{
	struct mysqlStruct oneSqlData;
	char readbuf[MAX_LEN];
	char* readbufPtr;
	int ret;
	openfile(readbuf);
	readbufPtr = readbuf;
	//printf("버퍼는 %s\n",readbufPtr);
	do{
		ret=bufToStruct(&readbufPtr, &oneSqlData);
		printf("%s\n", readbufPtr);
		sleep(1);
	}while(ret==-1);
	//bufToStruct(readbuf, &oneSqlData);

	return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "module1.h"
#include <string.h>
#include <stdlib.h>

int openfile(char* readbuf){


	//파일을 열어,
	//readbuf로 기록.

	int fd;
	//char buf[MAX_LEN];
	struct stat myfileStat;
	fd = open("./temperatureRecord.txt", O_RDONLY);
	if (fd == -1){
		perror("error to open file\n");
		return -1;
	}

	//읽을 파일 크기 확인.
	fstat(fd, &myfileStat);
	//최대 버퍼량 대비 파일이 큰지 확인
	if(MAX_LEN < myfileStat.st_size){
		perror("file is too big\n");
		//return  실패
		return -1;
	}
	
	read(fd, readbuf, myfileStat.st_size);
	//printf("버퍼는 %s\n",buf);
	close(fd);

	// ruturn 성공.
	return 0;
}

int bufToStruct(char** buf, struct mysqlStruct *sqlData){

	//buf를 읽어 날자, 시각, 온도로 분리.
	//,로 분리되어 delimiter로 분리..
	//한번 읽을때마다 buf 한 줄 내용을 sqlData로 이동.
	//성공하면 0,
	//마지막이면 1,
	//실패하면 -1을 return.

	size_t len, len2;
	char* temp;		//시작 위치
	len=strlen(*buf);
	char tempbuf[len];		//strtok로 작업할 내용. strtok이 원래 버퍼를 수정함.
	char *year,*month, *day, *hour, *minute, *temperature;
	int year2, month2, day2, hour2, minute2, temperature2;
	//strtok이 원래 버퍼를 잘라 버려.
	//임시로 카피해서 사용.
	//원래 포인터는 토큰 크기만큼 넘김.
	strcpy(tempbuf, *buf);

	//첫줄을 읽을 경우 무시할 방법 필요.
	//그냥 넣어서 에러, 정상 확인.
	temp = strtok(tempbuf, "\n");

	len=strlen(temp);
	year=strtok(temp, "-");
	//무슨 데이터인지 모르겠지만, 일단 숫자로 변경.
	year2=atoi(year);

	//buf 내용 삭제..temp 만큼.
	//buf 포인터를 temp 만큼 이동.
	//printf("함수 내부:포인터 이동 전\n %s",*buf);
	*buf=*buf+len+strlen("\n");

	//printf("함수 내부:포인터 이동 후\n %s",*buf);


	if(year2 < 2000 || year2 > 2100)
		return -1;

	//정상대로 진행.
	sqlData->year = year2;
	printf("year2 is %d\n",year2);
	month=strtok(temp,"-");
	month=strtok(temp,"-");
	month2=atoi(month);
	sqlData->month = month2;
}
Breakpoint 1, main () at main.c:13
13			ret=bufToStruct(&readbufPtr, &oneSqlData);
1: readbufPtr = 0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n"
2: &readbuf = (char (*)[200]) 0xbefff30c
3: *readbufPtr = 235 '\353'
(gdb) s
bufToStruct (buf=0xbefff308, sqlData=0xbefff3d4) at module1.c:42
warning: Source file is more recent than executable.
42	int bufToStruct(char** buf, struct mysqlStruct *sqlData){
(gdb) display &buf
4: &buf = (char ***) 0xbefff2d4
(gdb) display buf
5: buf = (char **) 0xbefff308
(gdb) display *buf
6: *buf = 0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n"
(gdb) l
37	
38		// ruturn 성공.
39		return 0;
40	}
41	
42	int bufToStruct(char** buf, struct mysqlStruct *sqlData){
43	
44		//buf를 읽어 날자, 시각, 온도로 분리.
45		//,로 분리되어 delimiter로 분리..
46		//한번 읽을때마다 buf 한 줄 내용을 sqlData로 이동.
(gdb) 
47		//성공하면 0,
48		//마지막이면 1,
49		//실패하면 -1을 return.
50	
51		size_t len, len2;
52		char* temp;		//시작 위치
53		len=strlen(*buf);
54		char tempbuf[len];		//strtok로 작업할 내용. strtok이 원래 버퍼를 수정함.
55		char *year,*month, *day, *hour, *minute, *temperature;
56		int year2, month2, day2, hour2, minute2, temperature2;
(gdb) 
57		//strtok이 원래 버퍼를 잘라 버려.
58		//임시로 카피해서 사용.
59		//원래 포인터는 토큰 크기만큼 넘김.
60		strcpy(tempbuf, *buf);
61	
62		//첫줄을 읽을 경우 무시할 방법 필요.
63		//그냥 넣어서 에러, 정상 확인.
64		temp = strtok(tempbuf, "\n");
65	
66		len=strlen(temp);
(gdb) 
67		year=strtok(temp, "-");
68		//무슨 데이터인지 모르겠지만, 일단 숫자로 변경.
69		year2=atoi(year);
70	
71		//buf 내용 삭제..temp 만큼.
72		//buf 포인터를 temp 만큼 이동.
73		//printf("함수 내부:포인터 이동 전\n %s",*buf);
74		*buf=*buf+len+strlen("\n");
75	
76		//printf("함수 내부:포인터 이동 후\n %s",*buf);
(gdb) b 74
Breakpoint 3 at 0x10814: file module1.c, line 74.
(gdb) n
53		len=strlen(*buf);
4: &buf = (char ***) 0xbefff2d4
5: buf = (char **) 0xbefff308
6: *buf = 0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n"
(gdb) c
Continuing.

Breakpoint 3, bufToStruct (buf=0xbefff308, sqlData=0xbefff3d4) at module1.c:74
74		*buf=*buf+len+strlen("\n");
4: &buf = (char ***) 0xbefff2d4
5: buf = (char **) 0xbefff308
6: *buf = 0xbefff30c "날자, 온도\n2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n"
(gdb) n
79		if(year2 < 2000 || year2 > 2100)
4: &buf = (char ***) 0xbefff2d4
5: buf = (char **) 0xbefff308
6: *buf = 0xbefff31b "2020-7-9 10:00:00, 24.5\n2020-7-9 10:01:00, 24.5\n2020-7-9 10:02:00, 24.5\n2020-7-9 10:03:00, 24.5\n"
(gdb) 

아래 사이트를 찾아 봤는데, 잘 이해가 안된다. 디버거로 주소 확인하는게 가장 확실했다. ㅠㅠ. 별 내용도 없는데, 왜케 오래걸리는지…

https://www.geeksforgeeks.org/double-pointer-pointer-pointer-c/
https://stackoverflow.com/questions/766893/how-do-i-modify-a-pointer-that-has-been-passed-into-a-function-in-c
https://chanywa.com/343

이 글 공유하기:

  • Tweet
발행일 2020-07-10글쓴이 이대원
카테고리 생활코딩 태그 c, linux, system program

댓글 남기기응답 취소

이 사이트는 Akismet을 사용하여 스팸을 줄입니다. 댓글 데이터가 어떻게 처리되는지 알아보세요.

글 내비게이션

이전 글

Linux System Programming

다음 글

자율적 자가 격리 썰

2025 5월
일 월 화 수 목 금 토
 123
45678910
11121314151617
18192021222324
25262728293031
4월    

최신 글

  • common mode, differential mode 2025-05-11
  • signal conditioner, 신호 처리기 2025-05-10
  • strain gage 2025-05-09
  • 칼만 필터 2025-05-01
  • positioner(I/P) 2025-04-26

카테고리

  • 산업계측제어기술사
  • 삶 자국
    • 책과 영화
    • 투자
  • 생활코딩
    • LEGO
    • ROS
    • tensorflow
  • 전기기사
  • 피아노 악보

메타

  • 로그인
  • 엔트리 피드
  • 댓글 피드
  • WordPress.org

페이지

  • 소개
  • 잔여 작업 조회
    • 작업 추가
    • 작업의 사진 조회
    • 작업 수정 페이지
  • 사진
    • GPS 입력된 사진
    • 사진 조회
  • 위치
    • 하기 휴가 방문지
    • 해외 출장

태그

android bash c docker driver FSM gps java kernel LEGO linux mysql network program opcua open62541 plc programmers python raspberry reinforcementLearning ros state space system program tensorflow transfer function 경제 미국 민수 삼국지 세계사 실기 에너지 역사 유전자 일본 임베디드 리눅스 전기기사 조선 중국 채윤 코딩 테스트 통계 한국사 한국어

팔로우하세요

  • Facebook
now0930 일지
WordPress로 제작.
 

댓글 로드중...