【C言語】配列の添え字に文字型charを避け整数型intを使おう

warning: array subscript has type ‘char’

警告:配列の添え字にchar 型
[-Wchar-subscripts]


■1.配列の添え字に不適切なchar型

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

char mystrlen(const char string[]){
    char    i;
    for(i = 0;string[i] != '\0';i++){
        ;
    }
    return  i;
}
int main(void){
    char    longstr[512];
    memset(longstr,'X',sizeof(longstr));
    longstr[511] = '\0';
    
    printf("%d\n",mystrlen(""));
    printf("%d\n",mystrlen("123"));
    printf("%d\n",mystrlen(longstr));
}

char型は符号付きか、符号無しかコンパイラに依存するので
配列の添え字に使うのは不適切です。
char が符号無しの時添え字は0~255までしか参照できません。
char が符号付きの時添え字は-128~127までしか参照できません。
※正確にはご自身の環境のCHAR_MIN/CHAR_MAXを参照ください。


■2.添え字にキャストする(非推奨)

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

char mystrlen(const char string[]){
    char    i;
    for(i = 0;string[(signed char)i] != '\0';i++){
        ;
    }
    return  i;
}
int main(void){
    char    longstr[512];
    memset(longstr,'X',sizeof(longstr));
    longstr[511] = '\0';
    
    printf("%d\n",mystrlen(""));
    printf("%d\n",mystrlen("123"));
    printf("%d\n",mystrlen(longstr));
}

型を見直さないでとにかくキャストするのは悪い習慣です。


■3.signed char型の添え字(非推奨)

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

signed char mystrlen(const char string[]){
    signed char    i;
    for(i = 0;string[i] != '\0';i++){
        ;
    }
    return  i;
}
int main(void){
    char    longstr[512];
    memset(longstr,'X',sizeof(longstr));
    longstr[511] = '\0';
    
    printf("%d\n",mystrlen(""));
    printf("%d\n",mystrlen("123"));
    printf("%d\n",mystrlen(longstr));
}

signed char型を使うとこの警告は消えますが、
狭い型を使うと効率の悪いコードが生成され、
なおかつ無限ループのリスクが残ります。


■4.unsigned char型の添え字(非推奨)

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

unsigned char mystrlen(const char string[]){
    unsigned char    i;
    for(i = 0;string[i] != '\0';i++){
        ;
    }
    return  i;
}
int main(void){
    char    longstr[512];
    memset(longstr,'X',sizeof(longstr));
    longstr[511] = '\0';
    
    printf("%d\n",mystrlen(""));
    printf("%d\n",mystrlen("123"));
    printf("%d\n",mystrlen(longstr));
}

unsigned char型を使うとこの警告は消えますが、
狭い型を使うと効率の悪いコードが生成され、
なおかつ無限ループのリスクが残ります。


■5.int型の添え字(推奨)

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

int mystrlen(const char string[]){
    int    i;
    for(i = 0;string[i] != '\0';i++){
        ;
    }
    return  i;
}
int main(void){
    char    longstr[512];
    memset(longstr,'X',sizeof(longstr));
    longstr[511] = '\0';
    
    printf("%d\n",mystrlen(""));
    printf("%d\n",mystrlen("123"));
    printf("%d\n",mystrlen(longstr));
}

物を数えるのに自然なint型を使うと警告は消え、
効率の良いコードが生成されます。


■6.アンケート

7
配列の添え字によく使う型を教えてください