スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

配列のポインタ

以前、配列のポインタについて悩んで記事にした事があった。
この間届いた「明快 C++」という本を読んで少し理解が深まったので追記。

int a[5];
a 単体で表記すると &a[0] を指す

ただし例外が3個あるそうで
sizeof(a) 
typeof(a)
&a 
だけは「先頭要素へのポインタ」ではなく「配列全体」に対して演算子が適用される

だそうだ。

関数の引数を通じて再現した配列(一度ポインタとなっている)に対してsizeofを適用してもこの例外が発生してくれないので思った挙動にならなかったわけだ。

ねよっと。


スポンサーサイト

ただのメモ

ただのメモ


ASCII制御文字の入力方法
コード 10進 16進 入力
NUL 0 00 Ctrl+Space or Ctrl+@(*)
SOH 1 01 Ctrl+A
STX 2 02 Ctrl+B
ETX 3 03 Ctrl+C
EOT 4 04 Ctrl+D
ENQ 5 05 Ctrl+E
ACK 6 06 Ctrl+F
BEL 7 07 Ctrl+G
BS 8 08 Ctrl+H or Backspace
HT 9 09 Ctrl+I or Tab
LF 10 0A Ctrl+J(**)
VT 11 0B Ctrl+K
FF 12 0C Ctrl+L
CR 13 0D Ctrl+M(**)
SO 14 0E Ctrl+N
SI 15 0F Ctrl+O
DLE 16 10 Ctrl+P
DC1 17 11 Ctrl+Q
DC2 18 12 Ctrl+R
DC3 19 13 Ctrl+S
DC4 20 14 Ctrl+T
NAK 21 15 Ctrl+U
SYN 22 16 Ctrl+V
ETB 23 17 Ctrl+W
CAN 24 18 Ctrl+X
EM 25 19 Ctrl+Y
SUB 26 1A Ctrl+Z
ESC 27 1B Ctrl+[ or Escape(*)
FS 28 1C Ctrl+\(*)
GS 29 1D Ctrl+](*)
RS 30 1E Ctrl+^(*)
US 31 1F Ctrl+_(*)
DEL 127 7F Delete



ねよっと。

メモリについて

プログラムしているのにメモリについてあんまり分かっていなかったので調べてみた。
C言語でメモリを理解するにはざっくりと
・コード(code)
・データ(data)
・ヒープ(heap)
・スタック(stack)

の4つに分けて考える。

コード (code) 
プログラム自体が配置される部分。
データ(data) 
グローバル変数やローカル変数など自動変数以外のものが配置される部分。
ヒープ(heap) 
mallocによって割り当てられるための領域。(処理系によっては存在しない)
スタック(stack) 
なんぞこれ。


詳しく調べてみた。

データの一時待避に利用される。
機構的にはFIFO(First-In Last-Out)と呼ばれるもので構成されている。
イメージ的には細長い入れ物?で、重ねて物をしまうと先にしまったものは後から入れたものを全部出さないと取り出せない。
C言語はスタックを自動変数のメモリ領域として利用している。
実際の例
・関数開始時にその関数内で使う自動変数の分だけダミーのデータをスタックに押し込む。
・その時スタック上に取られたメモリを自動変数用として利用。
・関数終了時にこれらを取り除く。

通常スタックはあまり大きくないため、自動変数に大きな配列などを確保したり、再帰関数の終了条件の設定を間違えたりするとスタックオバーフローを起こす。
とのこと。


昔作ったサーバーシステムで実際にこれが起きた。だめじゃん。
自動変数に大きな構造体を持たせたためにエラーが起きたのを記憶している。
対策は簡単
上の4つの区切りでいうところのデータ(data)かヒープ(heap)に移動させてやればよい。
具体的には
・static を付ける。
・グローバル変数にする。
・mallocで確保。


上記の方法以外で膨大なスタックを管理したい時の方法(調べたけど私は使ってなかったりする)
実行側で管理する
・Linuxの場合は実行ファイル(/etc/init.d/~)の中にulimit -s サイズ(KB)と記載することでスタックサイズを変えられる
(デフォルト以下を設定することはできない)
またこのプログラムで作成したスレッドはすべてスタックサイズを継承するみたい


プログラム側で管理する
推奨された方法かは疑問だけれどスレッドオプションにてサイズ変更ができるそうだ
・pthread_attr_setstacksize(attrアドレス,サイズ);を利用する。
pthread_attr_getstacksizeで確認もできる



少しだけ賢くなった。    気がする

ねよっと。

C の ++

C言語をやり始めて半年ほど。sizeofの次にやられたことです。

とある関数

void hoge(int *a){
*a++;
printf("%d\n",*a);
}


1を渡したら2って出るんじゃないの!

って話です。

「++」と「*」の優先度って「++」の方が高いなんて!!!

どうみたって弱そうじゃん!(筆者は優先度を強さのイメージで捉えているようです)

むぅ。

(*a)++;

とするか

*a += 1;

とすればOKっす。


ねよっと。

sizeofの罠 の続編 &RiSKさんへの返信

RiSK様、ご指摘ありがとうございます。
sizeofと配列の知識に間違いがあったことが理解できました。

しかし指摘いただいた点の誤解ではなかったようなので追記しておきます。
引数に配列を渡す時、配列が(暗黙に)型変換され,配列の先頭要素へのポインタが渡されるということは知っておりました。

というかすべてのプログラムを
void f(int a[])
ではなく
void f(int *a)
で書いていたりしました。

私が勘違いしていた点は
sizeofに配列の頭のポインタを渡せば大きさが帰ってくるものだと思っていた点(アホ)
です
ええ、あれなんです。

void show(char * test)
{
printf("%d\n",sizeof(test));
}

int main(
{
char test[100];

printf("%d\n",sizeof(test));
printf("%d\n",sizeof(&test[0]));
show(test);
}
結果:
100
4
4




関数どうのこうのよりも
printf("%d\n",sizeof(test));

printf("%d\n",sizeof(&test[0]));
の結果が違うことがわかっていなかったのです。



コメントありがとうございました!
理解が深まり感謝しております。






ねよっと。
プロフィール

あしゅ

Author:あしゅ
ぷぃぷぃ日常。
いつのまにか雑記ブログに。

カテゴリ
最新記事
検索フォーム
最新コメント
リンク
このブログをリンクに追加する
ブロとも申請フォーム

この人とブロともになる

カウンター
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。