🦔
C言語のポインタとかポインタ変数とか
arrayとpointer
arrayとポインターはまず全く別物。
ポインタ変数に[1], [2]とかつけるのは、配列型に[1], [2]とつけて要素番号にアクセスするのと、たまたま同じ[]
を使っているだけで、意味は異なる。
ポインタ変数の場合は、アドレスに足し算を使う。
- https://www.programiz.com/c-programming/c-pointers-arrays
- https://www.studytonight.com/c/pointers-with-array.php
- https://web.stanford.edu/class/archive/cs/cs107/cs107.1206/lab3/
sizeofはoperator, not function.
stackoverflowのarrayのサイズを演算する方法
size_t n = sizeof(a) / sizeof(a[0]);
のa[0]
は、「配列の変数aの最初の要素を指定」という書き方だが
size_t n = sizeof(a) / sizeof(*a);
ともかける?。こちらは、aは配列の先頭のポインタ変数なので、そこから値を取り出すというイメージ。
#include <stdio.h>
int main() {
int arr[3] = {10,20,30};
int* t = arr;
printf("%p\n", t);
printf("arr: %lu\n", arr);
printf("t: %lu\n", t);
printf("the size of arr : %lu\n", sizeof(arr)); // int型のarrayなので要素数 * int型のサイズ = 12
printf("the size of *arr : %lu\n", sizeof(*arr)); // arrの先頭の要素の
printf("the size of t : %lu\n", sizeof(t)); // ポイント変数なので8
// ポインタ変数でやった場合
printf("t[0]: %d\n", t[0]);
printf("t[1]: %d\n", t[1]);
printf("t[2]: %d\n", t[2]);
// printf("%d\n", t[3]);
// arrのindexでアクセスした場合
printf("arr[0]: %d\n", arr[0]);
printf("arr[1]: %d\n", arr[1]);
printf("arr[2]: %d\n", arr[2]);
// printf("%d\n", arr[3]);
// arrは配列先頭のポインタなので、*arrだと、arrの先頭要素の値にアクセス可能
// arr+1は、配列の先頭から次のポインタにアクセス。
printf("*arr: %d\n", *arr);
printf("*(arr+1): %d\n", *(arr+1));
printf("*(arr+2): %d\n", *(arr+2));
return 0;
}
メモ
#include <stdio.h>
int main() {
int a[10];
int* p = a;
printf("%lu\n", sizeof(a)); // a全体のsizeなので40
printf("%lu\n", sizeof(a[0])); // arrayの先頭の要素、つまりintのsizeなので4
printf("%lu\n", sizeof(a) / sizeof(a[0])); // 要素数が計算できる
printf("=========\n");
printf("%lu\n", sizeof(p)); // pというポインタ変数のsizeなので 8
printf("%lu\n", sizeof(int*)); // int型のポインタ変数のsizeなので 8
printf("%d\n", sizeof(p) == sizeof(int*)); // same sizeなのでtrue = 1
printf("%d\n", sizeof(*p) == sizeof(int)); // *pは、int型のpというポインタ変数の値なので4, sizeof(int)もint型のsizeなので4。よって1
return 0;
}
sizeof
オペレーターはmain関数以外のfunction内では、main関数での挙動は期待できない
-> https://www.jpcert.or.jp/sc-rules/c-arr01-c.html
関数 clear() が配列の要素を 0 で初期化する。この関数は、int array[] として宣言された引数を 1 つ取り、12 個の int からなる静的配列が渡されている。関数 clear() は sizeof(array) / sizeof(array[0]) という構文を使用して配列内の要素数を求めている。しかし、array は引数なので、ポインタ型となる。したがって、sizeof(array) は sizeof(int *) に等しくなる。たとえば、sizeof(int) == 4 および sizeof(int *) == 4 であるアーキテクチャ(IA-32など)の場合、渡された配列のサイズに関係なく、式 sizeof(array) / sizeof(array[0]) の値は 1 となり、配列の残りの要素は初期化されないままになる。
32 bitと64 bit
おまけ C++
#include <iostream>
using namespace std;
// 引数で私た変数を書き換える
void count_with_reference(int &cnt){
cnt++;
}
void count(int cnt){
cnt++;
}
int main()
{
int cnt = 1;
cout << "before cnt: " << cnt << endl; // 1
count(cnt);
cout << "after count cnt: " << cnt << endl; // 1
count_with_reference(cnt);
cout << "after count_with_reference cnt: " << cnt << endl; // 2
return 0;
}
Discussion