【C言語】
配列の添字に文字型charを避け安全で効率的な整数型intを使おう

配列の添字

warning: array subscript has type ‘char’

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


■配列の添字に不適切な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を参照ください。


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

#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));
}

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


■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型を使うとこの警告は消えますが、
狭い型を使うと効率の悪いコードが生成され、
なおかつ無限ループのリスクが残ります。


■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型を使うとこの警告は消えますが、
狭い型を使うと効率の悪いコードが生成され、
なおかつ無限ループのリスクが残ります。


■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型を使うと警告は消え、
効率の良いコードが生成されます。


■アンケート

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