【C言語】
NULLにキャストは冗長!
不要なキャストを削除しよう

if(ptr==(void *)NULL) NULLに キャスト不要

warning: cast from pointer to integer of different size

警告:ポインタ型を型幅の違う整数型にキャストした
[-Wpointer-to-int-cast]


■(int)NULL

#include    <stdio.h>
#include    <string.h>
void f1(void){
    char    buf[1024];
    memset(buf,(int)NULL,sizeof(buf));//NG
}

「0 はマジックナンバーなので使用禁止!」と
教育された初級者が
0と書けず
NULLと書き、
コンパイラに警告されて (int)NULL とキャストする場合が多いです。


➡(int)NULL➡0に修正

void f2(void){
    char    buf[1024];
    memset(buf,0,sizeof(buf));//OK
}

0はマジックナンバーではないので素直にべたで0と書く。

■(char)NULL

size_t f3_strlen(char *s)
{
  char  *p;
  for (p = s; *p != (char)NULL; p++)//NG
    ;
  return p - s;
}

「文字列の最後にはNULL文字がある」と教育された初級者が
‘\0’と書かずに
NULLと書き、
コンパイラに警告されてキャストする場合が多いです。

➡(char)NULL➡’\0’に修正

size_t f4_strlen(char *s)
{
  char  *p;
  for (p = s; *p != '\0'; p++)//OK
    ;
  return p - s;
}

「文字列の最後には終端文字’\0′がある」と教育しましょう。

■問題:文字列にキャストすると?

warning: suspicious usage of ‘sizeof(A*)’; pointer to aggregate

警告:余計なキャストが疑わしい
[misc-sizeof-expression]

問題:次のプログラムは何と表示されるでしょうか?

#include    <stdio.h>
#include    <string.h>
#define STRING  (const char *)"123456789abcdef" 
int main(void)
{
  printf("%ld\n",sizeof(        "123456789abcdef"));
  printf("%ld\n",sizeof((char *)"123456789abcdef"));
  printf("%ld\n",sizeof(STRING));
  printf("%ld\n",strlen(STRING));
}

sizeof((char *)“123456789abcdef”)は余計なキャストをしているため、文字列リテラル”123456789abcdef”は無視され
sizeof(char *)と同じ結果が求まります。

sizeof(STRING)も同様ですが、
キャストがマクロで隠されるのでより問題の発見が難しくなります。

●解答

16
8
8
15

■(void *)NULL

warning: redundant cast to the same type

警告:冗長キャストがコードを汚す
[google-readability-casting]

#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
int main(void)
{
    char    *cp = (char *)malloc(sizeof(char)*(int)1024);
    if((char *)cp == (char *)NULL){
        printf("メモリ確保失敗\n");
        return  (int)1;
    }
    memset((void *)cp,(int)'\0',sizeof(char)*1024);
    strncpy((char *)cp,(const char *)"a-b-c",(int)6);
    char    *sp = strchr((char *)cp,(int)'-');
    if((char *)sp == (char *)NULL){
        printf((const char *)"'-'検索失敗\n");
        return  (int)1; 
    }
    printf((const char *)"%s\n",(char *)sp);
    if((char *)cp != (char *)NULL){
        free((void *)cp);
    }
    return  (int)0;
}

●例1:malloc()/free()にキャストしたがる理由

C-FAQ7.7

http://www.kouno.jp/home/c_faq/c7.html#7

MEM02-C. Immediately cast the result of a memory allocation function call into a pointer to the allocated type

ここの末尾のコメント欄の議論が面白い

●例2:NULLにキャストしたがる理由

NULLについて

http://f4.aaacafe.ne.jp/~pointc/log1018.html

●例3:文字定数にキャストしたがる理由

推測⇒
C言語では文字定数がint型だと知らないから
int型に明示的にキャストする?

●例4:memset/cpy/cmpの引数にキャストしたがる理由

推測⇒
K&Rという初代C言語では汎用ポインタの void * がなく
char *で代用していた大昔の習慣が現代に継承されている?

➡不要なキャストを削除すると読みやすい

#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
int main(void)
{
    char    *cp = malloc(1024);
    if(cp == NULL){
        printf("メモリ確保失敗\n");
        return  1;
    }
    memset(cp,'\0',1024);
    strcpy(cp,"a-b-c");
    char    *sp = strchr(cp,'-');
    if(sp == NULL){
        printf("'-'検索失敗\n");
        free(cp);
        return  1;
    }
    printf("%s\n",sp);
    free(cp);
}

不要キャストを削除してサッパリしませんか?