char変数について
以下のように5文字サイズのchar型変数に6文字を入れた場合
char str2[5] = "test23";
import numpy as np
arr = np.array([1, 2, 3])
以下のようにコンパイル時に警告がでる
hello.c:5:16: 警告: initializer-string for array of ‘char’ is too long
5 | char str2[5] = "test23";
| ^~~~~~~~
以下のように5文字分のサイズに5文字を入れた場合
char str2[5] = "test2";
エラーにならず正常に稼働するがNULLは入らない(out2-5は次のアドレス)
out2-0:t
out2-1:e
out2-2:s
out2-3:t
out2-4:2
out2-5:
16進数表記(utf8)で出力する(printfでフォーマット指定子を%x)
out2-0:74
out2-1:65
out2-2:73
out2-3:74
out2-4:32
out2-5:0
■iint型の配列
int iarray5[5] = {11111, 222222, 3333333, 44444444};
printf("iarray5[0]: %d\n", iarray5[0]);
printf("iarray5[1]: %d\n", iarray5[1]);
printf("iarray5[2]: %d\n", iarray5[2]);
printf("iarray5[3]: %d\n", iarray5[3]);
printf("iarray5[4]: %d\n", iarray5[4]);
printf("iarray5: %p\n", &iarray5);
iarray5[0]: 11111
iarray5[1]: 222222
iarray5[2]: 3333333
iarray5[3]: 44444444
iarray5[4]: 0
iarray5: 0x7fff2e8eaee0
■charの配列(配列の配列)
以下は要素数6の配列を5つの要素で定義
char array5[5][6] = {"test1", "test2", "test3", "test4"};
printf("array5[0]: %s\n", array5[0]);
printf("array5[1]: %s\n", array5[1]);
printf("array5[2]: %s\n", array5[2]);
printf("array5[3]: %s\n", array5[3]);
printf("array5[4]: %s\n", array5[4]);
内容を確認
array5[0]: test1
array5[1]: test2
array5[2]: test3
array5[3]: test4
array5[4]:
■iint型の配列の関数渡し
以下のどの方法でも同じ結果になるが2番目が一般的らしい
int iarray5[5] = {11111, 222222, 3333333, 44444444};
int numlen = sizeof(iarray5) / sizeof(int);
ret = psetMsg(iarray5, numlen);
ret = isetMsg(iarray5, numlen);
ret = asetMsg(iarray5, numlen);
int psetMsg(int *pint, int numlen){
printf("pint address: %p\n", pint);
printf("*pint: %d\n", *pint);
printf("numlen: %d\n", numlen);
return 0;
}
int isetMsg(int pint[], int numlen){
printf("pint address: %p\n", pint);
printf("*pint: %d\n", pint[0]);
printf("numlen: %d\n", numlen);
return 0;
}int asetMsg(int aint[5], int numlen){
printf("pint[6] address: %p\n", aint);
printf("*pint[6]: %d\n", aint[0]);
printf("numlen: %d\n", numlen);
return 0;
}
内容を確認
pint address: 0x7ffe2ad1bd40
*pint: 11111
numlen: 5
pint address: 0x7ffe2ad1bd40
*pint: 11111
numlen: 5
pint[6] address: 0x7ffe2ad1bd40
*pint[6]: 11111
numlen: 5
■ポインタ演算
以下のポインタを渡す関数部分を変更
int psetMsg(int *pint, int numlen){
int *plint;
printf("pint address: %p\n", pint);
printf("*pint: %d\n", *pint);
printf("*(pint + 1): %d\n", *(pint + 1));
printf("*(pint + 2): %d\n", *(pint + 2));
printf("pint[1]: %d\n", pint[1]);
printf("pint[2]: %d\n", pint[2]);
printf("*pint: %d\n", *pint);
*plint++ += *pint++;
printf("*pint: %d\n", *pint);
printf("*plint++: %d\n", *plint);
printf("*pint++: %d\n", *pint++);
*pint = *pint++;
printf("*pint++: %d\n", *pint++);
printf("numlen: %d\n", numlen);
return 0;
}
内容を確認
pint address: 0x7ffd88dee440
*pint: 11111
*(pint + 1): 222222
*(pint + 2): 3333333
pint[1]: 222222
pint[2]: 3333333
*pint: 11111
*pint: 222222
*plint++: 222222
*pint++: 222222
*pint++: 3333333
numlen: 5
文字列操作
■文字列の格納
リテラルによる初期化はOK
char str1[] = "test";
配列による初期化はNG
char str1[] = "test";
char str2[] = str1;
分割して格納する方法
char str3[5] = {"t", "e", "s", "t","\0"};
以下はポインタ変数(アドレスを代入する変数)への格納となってしまうのでNG
str1= "test";
以下はポインタ変数同士の比較となってしまうので常に異なる
if ( str1 == str2 ) {
}
初期化以外で配列へまとまった値を入れたい場合は関数を使う
文字列型のデータのコピーは数値型のデータのように「=」記号を使って代入コピーしようとしても、意図通りにならない。
strcpyはコピー元の`\0`までコピーする
strcpy(str6, str2)
NULL, \0, 0について
■NULL
ヌルポインタを意味する。で次のように定義されている。
#define NULL ((void *)0)
■\0(ヌル文字)
(char)0と同じ
■0
(int)0として扱う
結局、(char)0も(int)0もC言語(環境UTF-8)上では文字コードは0x00で同じなため、違いはない。
※C++だと変わってくる?<<初期化について(memset)>>
void *memset(void *buf, int ch, size_t n);
第一引数はメモリのポインタ
第二引数はセットする値
第三引数はセットするサイズ
例 memset(tmp, '\0', sizeof(tmp));