프로그래밍/C2015.07.11 21:24

새로운 노드의 주소는 항상 같은 offset을 두고 생성될까? 적어도 주소의 절대값이 줄지는 않은 거 처럼 보이는데....

신고
Posted by code cat
프로그래밍/C2015.01.15 18:11
error: aggregate value used where an integer was expected

위와 같은 에러를 본다면, 아마도 구조조체의 멤버 대신 구조체를 직접 integer로 캐스팅하려는 실수를 했을 때 나오는 것이다.

신고
Posted by code cat
프로그래밍/C2014.09.11 10:50

시간날때 마져 다 읽어볼려고 남기는데, 재밌다.  물론 나도 C에는 call-by-reference는 없다고 생각하는 사람이지만, 읽어보면 재밌다.

https://kldp.org/node/119844

신고
Posted by code cat
프로그래밍/C2014.06.05 09:17

for (i=0; i < size && iterator->next != NULL; i++, iterator=iterator->next)


for 문 조건처리에서는 위와 같이 &&나 ||를 써줘야 한다. 만약 대신에 ','를 쓴다면 


for (i=0; i < size, iterator->next != NULL; i++, iterator=iterator->next)


앞의 조건, i < size는 그냥 무시가 되어 버리니 조심하자.  하지만 처리 부분에서는 ','를 써서 처리하면 된다.

신고
Posted by code cat
프로그래밍/C2014.06.02 16:29

strerror

#include <stdio.h>

#include <string.h>


void main()

{

  FILE *fp;

  if ((fp = fopen("data.txt", "r")) == NULL) {

    fprintf(stderr, "ERROR: %s\n", strerror(errno));

    exit(1);

  }

  exit(0);

}


strerror는 errno를 받아서 실패한 원인에 대한 메세지를 리턴한다.


그런데 perror는 더 편리하다.

perror

#include <stdio.h>


void main()

{

  FILE *fp;

  if ((fp = fopen("data.txt", "r")) == NULL) {

    perror("ERROR");  // 오류가 발생했을 때 오류 출력시에 앞에 붙는 PREFIX를 인자로 받는다.

    exit(1);

  }

  exit(0);

}


신고
Posted by code cat
프로그래밍/C2014.05.29 11:22

출처: http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc

In this question, someone suggested in a comment that I should not cast the results of malloci.e:

int *sieve = malloc(sizeof(int)*length);

rather than:

int *sieve = (int *)malloc(sizeof(int)*length);

Why would this be the case?


No; you don't cast the result, since:

  • It is unnecessary, as void * is automatically and safely promoted to any other pointer type in this case.
  • It can hide an error, if you forgot to include <stdlib.h>. This can cause crashes, in the worst case.
  • It adds clutter to the code, casts are not very easy to read (especially if the pointer type is long).
  • It makes you repeat yourself, which is generally bad.

As a clarification, note that I said "you don't cast", not "you don't need to cast". In my opinion, it's a failure to include the cast, even if you got it right. There are simply no benefits to doing it, but a bunch of potential risks, and including the cast indicates that you don't know about the risks.

Also note, as commentators point out, that the above changes for straight C, not C++. I very firmly believe in C and C++ as separate languages.

To add further, your code needlessly repeats the type information (int) which can cause errors. It's better to dereference the pointer being used to store the return value, to "lock" the two together:

int *sieve = malloc(length * sizeof *sieve);

This also moves the length to the front for increased visibility, and drops the redundant parentheses with sizeof; they are only needed when the argument is a type name. Many people seem to not know (or ignore) this, which makes their code more verbose. Remember: sizeof is not a function! :)


@sirgeorge - without the prototype/decl (in stdlib.h), a C compiler might/will assume that malloc returns an int. Then the compiler generates code for the call in question as if it is getting an int. Then, say, you are compiling for a platform where pointers and ints do not have the same size, and you cast the returning int into a pointer. Bad juju. And the compiler, upon seeing the casting, won't give you a warning in this case. But if you don't cast it, then the compiler will complain abou the int-to-ptr assignment (and you will be able to detect the missing include for stdlib.h) –  luis.espinal Mar 14 '12 at 19:28 

신고

'프로그래밍 > C' 카테고리의 다른 글

for 문 multiple 조건 & 처리  (0) 2014.06.05
strerror 사용법, perror 사용법  (0) 2014.06.02
malloc 를 캐스팅 하지 말자.  (0) 2014.05.29
strtok에 NULL을 전달하는 이유  (0) 2014.05.29
함수포인터 & typdef를 이용한 함수포인터  (0) 2014.05.07
ternary operator  (0) 2014.04.13
Posted by code cat
프로그래밍/C2014.05.29 09:32

strtok를 쓸 때, 왜 두번째 콜에서 NULL을 넘겨줄까? 그냥 그러려다 찾아보았다.


char str[] = "Hello World. How are you?";
        char delim[] = " ";
        char *ptr;

ptr = strtok(str, delim);
        printf("%s\n", ptr);
        while(ptr = strtok(NULL, delim))
            printf("%s\n", ptr);


다음은 strtok.c 의 내용이다.(glibc 2.19버전)


18 #include <string.h>
19 
20 
21 static char *olds;
22 
23 #undef strtok
24 
25 /* Parse S into tokens separated by characters in DELIM.
26  If S is NULL, the last string strtok() was called with is
27  used. For example:
28  char s[] = "-abc-=-def";
29  x = strtok(s, "-"); // x = "abc"
30  x = strtok(NULL, "-="); // x = "def"
31  x = strtok(NULL, "="); // x = NULL
32  // s = "abc\0=-def\0"
33 */
34 char *
36  char *s;
37  const char *delim;
38 {
39  char *token;
40 
41  if (s == NULL)
42  s = olds;
43 
44  /* Scan leading delimiters. */
45  s += strspn (s, delim);
46  if (*s == '\0')
47  {
48  olds = s;
49  return NULL;
50  }
51 
52  /* Find the end of the token. */
53  token = s;
54  s = strpbrk (token, delim);
55  if (s == NULL)
56  /* This token finishes the string. */
57  olds = __rawmemchr (token, '\0');
58  else
59  {
60  /* Terminate the token and make OLDS point past it. */
61  *s = '\0';
62  olds = s + 1;
63  }
64  return token;
65 }


41라인을 보면 NULL일 경우, static 변수 old로 대체한다. 아! 그래서 NULL을 써서 이어서 파싱이 되게 하는구나.  그리고 static변수라... 쓰레드 사용시에 문제가 있을 거 같다.

추가로 찾아본 내용을 보니,(http://ogoons.tistory.com/m/post/70) 다음과 같은 주의사항이 있다.


1. strtok()의 사용 후, 원본 문자열의 데이터를 보장할 수 없다.
2. visual studio 상위 버전에 문제가 있을 수 있다.
3. strtok()은 내부적으로 문자열 분리를 위해 static변수를 놓고 정적공유를 함으로 , thread-safe하지 않다.(음 역시)


따라서 위의 상황들을 개선한 strtok_s()를 쓰길 권장한다고 한다.


char str[] = "Hello World Good, Morning Sunshine";

char delim[] = " ,";

char *ptr;

char *context = NULL;

ptr = strtok_s(str, delim, &context);

printf("%s\n", ptr);

while(ptr = strtok_s(NULL, delim, &context))

printf("%s\n", ptr);


신고
Posted by code cat
프로그래밍/C2014.05.07 15:33


if 0로 묶여 있는 부분은 보통의 함수포인터를 부르는 방식이다.
하지만 이는 복잡해 보이고 혼란을 줄 수 있는 모양일 수 있다.  따라서 코드를 깔끔하게 보이기 위해 else로 묶여있는 부분을 보면 typedef를 통한 함수포인터 사용을 볼 수 있다.


typedef에 대한 부분이 혼란스러우면 아래와 같이 이해하면 좋다(출처:https://kldp.org/node/119822)

typedef를 빼면 변수 선언 붙이면 타입 선언이라고 이해하시면 편합니다.

unsigned int u32; // u32는 unsigned int 타입의 변수
typedef unsigned int u32; // u32는 unsigned int 타입

int (*func)(int, int); // func는 (int, int)를 받고 int를 리턴하는 함수에 대한 포인터 타입의 변수
typedef int (*func)(int, int); // func는 (int, int)를 받고 int를 리턴하는 함수에 대한 포인터 타입


신고
Posted by code cat
프로그래밍/C2014.04.13 20:27

출처: http://en.wikipedia.org/wiki/%3F:

GNU확장은 다음과 같이 값을 프로세싱을 한번 이상 할 경우, 문제가 되는 경우를 대비해 다음과 같이 operand를 스킵할 수 있게 한다.


a = x ? : y;


상기 라인은 아래와 같다.

a = x ? x : y;


만일 x가 expression이라면, 한번만 프로세싱된다.


신고
Posted by code cat
프로그래밍/C2013.11.24 00:11

자 아래를 보자

void DLL_PrintNodes(Node* head){

 Node* current;
 current = head;
 int idx = 0;

 while(current->NextNode != NULL) {
  printf("[%d] %d\n", idx++, current->Data);
  current = current->NextNode;
 }
}

 

문제가 보이는가? 실행하면...

 error C2143: 구문 오류 : ';'이(가) '형식' 앞에 없습니다.
 error C2065: 'idx' : 선언되지 않은 식별자입니다.

 

응???

linux에서 gcc 툴체인으로 작업하는 사람들은 위와 같은 반응을 보일텐데...

 

MSDN에서는 다음과 같이 말하고 있다.  C에서는 함수나 블록의 시작점에 지역변수들은 선언되야 하며, 함수가 선언이 아닌 명령어들을 실행하고 나서는 선언이 들어 올 수 없다고...

 

예) 

// C2143j.c
int main() 
{
    int i = 0;
    i++;
    int j = 0; // C2143 에러
}

 

그럼 왜 GCC에서는 괜찮은가? 그건 GCC가 위와 같은 코드를 GNU확장으로 허용하기 때문이다.  만약 ANSI나 C89등에 맞추어서 컴파일 되길 원한다면, -pedantic을 flag로 넘겨주면 된다.

신고
Posted by code cat

티스토리 툴바