トップページ⇒tech
1001コメント370KB

C言語なら俺に聞け(入門篇) Part 7

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2007/01/29(月) 19:03:00
C言語の入門者向け解説スレです。
・C++言語はスレ違いです。
・分からない事をなるべく詳しく書いて下さい。
・ソースコードを晒すと答えやすくなるかもしれません。
・質問者は最初にその質問をした時のレス番号を名前欄に書いて下さい。

前スレ
C言語なら俺に聞け(入門篇) Part 6
Part 6 http://pc10.2ch.net/test/read.cgi/tech/1167325490/

過去スレ
Part 1 http://pc8.2ch.net/test/read.cgi/tech/1146700389/
Part 2 http://pc8.2ch.net/test/read.cgi/tech/1153818463/
Part 3 http://pc8.2ch.net/test/read.cgi/tech/1160682950/
Part 4 http://pc8.2ch.net/test/read.cgi/tech/1162999861/
Part 5 http://pc8.2ch.net/test/read.cgi/tech/1165022193/

関連スレ
C/C++の宿題を片付けます 82代目
http://pc10.2ch.net/test/read.cgi/tech/1169575464/l50
くだすれC言語(初心者用)
http://pc10.2ch.net/test/read.cgi/tech/1153542424/l50
【ISO/ANSI/JIS】 C言語なら俺に聞け! Part 130
http://pc10.2ch.net/test/read.cgi/tech/1159613789/l50
【初心者歓迎】C/C++室 Ver.34【環境依存OK】
http://pc10.2ch.net/test/read.cgi/tech/1169039760/l50

【C 関数検索 man on WWW】 http://www.linux.or.jp/JM/index.html
0153デフォルトの名無しさん2007/02/04(日) 00:59:19
>>152
シグナルはよく分からないんですが、とにかくキーボードから
入力があったら無限ループを抜けるようにしたいんですが・・・
0154デフォルトの名無しさん2007/02/04(日) 00:59:20
#include <stdio.h>

main(){

int i,n;
for(i=1;i<=100;i++){
for(n=i-1;n>1;n--){
if(i%n == 0)
break;
}
if(n==1)printf("%d\n",i);
}
printf("全部表示したぞ!この包茎が\n",i);
}

1〜100の素数表示するプログラム書きました。
もっと簡潔なやつや効率いいのはどうすればいいですか。
0155デフォルトの名無しさん2007/02/04(日) 01:01:32
>>153
「linux signal」とかで検索したら、いっぱいでてくると思われ。
01561542007/02/04(日) 01:09:42
個人的に結構いいプログラムだと思う。どうよ
0157デフォルトの名無しさん2007/02/04(日) 01:19:19
総当りっていうな
結局それが一番速かったりするが
プログラムの価値はない
0158デフォルトの名無しさん2007/02/04(日) 01:19:25
>>155
すみません、初心者なのでsignalが理解出来ません。
0159デフォルトの名無しさん2007/02/04(日) 01:23:12
>>158
じゃ、kbhit()を使う方向で。
0160デフォルトの名無しさん2007/02/04(日) 01:28:13
>>159
conio.hがない場合はどうすればいいですか?
01611of22007/02/04(日) 01:29:49
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<fcntl.h>

enum{
  THREAD_RUNNING,
  THREAD_STOPPING,
  THREAD_FINISH
};

int is_enter_pressed(void)
{
  int fd_flag, ret=0;
  char buf[10];

  fd_flag=fcntl(0, F_GETFL);
  fcntl(0, F_SETFL, O_NONBLOCK);
  while(read(0, buf, sizeof(buf))>0) /* 不要な入力はすべて読み飛ばす */
    ret=1;
  fcntl(0, F_SETFL, fd_flag);

  return ret;
}
01622of22007/02/04(日) 01:30:31
void *aru_shori(void *arg){
  int *thread_status;
  int i;

  thread_status=arg;
  *thread_status=THREAD_RUNNING;
  for(i=0;i<30;i++){
    if(*thread_status!=THREAD_RUNNING)
      return NULL;
    printf("%s %d ある処理\n", __FUNCTION__, i);
    sleep(1);
  }
  *thread_status=THREAD_FINISH;
  return NULL;
}

int main(void){
  pthread_t th;
  volatile int th_status;

  pthread_create(&th, NULL, aru_shori, (void*)&th_status);
  printf("Enter を押すと途中で終了します\n");
  while(th_status==THREAD_RUNNING){
    if(is_enter_pressed()){
      th_status=THREAD_STOPPING;
      break;
    }
    sleep(1);
  }
  pthread_join(th, NULL);
  return 0;
}
01631542007/02/04(日) 01:30:38
>>157

すいませんでした
0164デフォルトの名無しさん2007/02/04(日) 01:34:16
>>160
>>161-162 をコピペして全角空白を削除(or 置換)
gcc 〜〜.c -lpthread
でコンパイル、リンク、実行してみて

あと名前とトリップを入れてくれると分かりやすいんだが
01651442007/02/04(日) 01:50:58
>>164
ありがとうございます。
しかし、実行してみた所Enterを押しても終了しないのですが・・・
0166デフォルトの名無しさん2007/02/04(日) 01:52:31
初版の独習Cを500円で買ったけど関数の書き方とかが違う・・・・
3200円出して第3版の買ったほうがいいかな・・・
0167デフォルトの名無しさん2007/02/04(日) 02:01:31
>>144 (>>165)
下のように変更して実行し、
「aru_shori 4 ある処理」が表示されたあたりで Enter を押した場合には、
どちらのメッセージが出ますか?

  pthread_join(th, NULL);
↓
  pthread_join(th, NULL);
  if(th_status==THREAD_STOPPING)
    printf("\n処理が中断されました\n");
  if(th_status==THREAD_FINISH)
    printf("\n処理は正常終了しました\n");
01681442007/02/04(日) 02:10:33
>>167
Enter を押してみましたが1行改行されるだけで何も起きません。
0169デフォルトの名無しさん2007/02/04(日) 02:16:08
>>144 (>>168)
>>161-162 がダメだったということは、多分これもうまくいかないんだろうけど
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>

int is_enter_pressed(void)
{
int fd_flag, ret=0;
char buf[10];

fd_flag=fcntl(0, F_GETFL);
fcntl(0, F_SETFL, O_NONBLOCK);
while(read(0, buf, sizeof(buf))>0) /* 不要な入力はすべて読み飛ばす */
ret=1;
fcntl(0, F_SETFL, fd_flag);

return ret;
}

int main(void){
int i;
printf("Enter を押すと途中で終了します\n");
for(i=0;i<30;i++){
if(is_enter_pressed()) break;
printf("%s %d ある処理\n", __FUNCTION__, i);
sleep(1);
}
return 0;
}
01701442007/02/04(日) 02:20:09
>>169
上手く行きました!!
本当にありがとうございました!
0171デフォルトの名無しさん2007/02/04(日) 02:49:56
mぅいやだあああああ
わかねーーーーー
0172デフォルトの名無しさん2007/02/04(日) 03:56:51
#include <stdio.h>

main(){
int x,y;/*ループのカウンタ*/
char c;/*キャラクタ番号*/

for(x = 2; x < 8; x++)
printf("16: 10:c | ");
printf("\n");
for(x = 2; X < 8; x++)
printf("---------\n");
printf("\n");

for(y = 0; y < 16; y++)
{
for(x = 2; X < 8; x++)
{
c = x * 16 + y;
printf("%2x:%3d:%c |",c,c,c);
}
printf("\n");
}

return 0;
}

エラー E2451 aaa.c 10: 未定義のシンボル X(関数 main )
*** 1 errors in Compile ***

これの何が違うかわかりませんので、ご指摘お願い致します。
0173デフォルトの名無しさん2007/02/04(日) 03:58:09
自己解決しマスタ
0174デフォルトの名無しさん2007/02/04(日) 04:07:29
>>172
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int c;
while ((c = getchar()) != EOF) {
putchar(tolower(c));
}
return 0;
}
このプログラムをコンパイルして実行ファイルを作り、
実行ファイル名 < aaa.c > aaaa.c
と実行して、作られたaaaa.cをコンパイルする。
0175デフォルトの名無しさん2007/02/04(日) 19:39:25
>>154>>156
良いかどうかは分かりませんが

#include <stdio>
#define MAX 100
int main()
{
unsigned char c[MAX]={0};
int i,k;
for(i=2;i<MAX;i++)
{
if(c[i]==1) continue;
for(k=i*2;k<MAX;k+=i)
{
c[k]=1;
}
printf("%d\n",i);
}
return 0;
}
0176デフォルトの名無しさん2007/02/05(月) 00:24:34
#include<stdio.h>

main()
{
int num1, num2, op;

printf("number1:");
scanf("%d",&num1);
printf("number2:");
scanf("%d",&num2);

printf("0to add,1to multiply:");
scanf("%d",&op);

if(op==0)
printf("%d",num1 + num2);
else
printf("%d",num1 * num2);
}
0を選んでも積を求めてしまうのは何故でしょうか?
0177デフォルトの名無しさん2007/02/05(月) 00:35:53
printf("%d",op);
ってみれば何かわかるんじゃない
0178デフォルトの名無しさん2007/02/05(月) 00:38:56
自己解決しました
コードを修正しても上書き保存をしてなかったようです
0179デフォルトの名無しさん2007/02/05(月) 00:48:45
すいません複数のファイル合わせてコンパイルするやり方がわかりません。
くだらない質問ですが初心者に教えてくださいお願いします。
0180デフォルトの名無しさん2007/02/05(月) 01:10:02
#include <stdio.h>

main(){
int i;
int a[] = {1,2,3,4};

for(i = 3; i >= 0; i--)
printf("%d ",a[i]);
printf("\n");

return 0;
}

実行結果が 4 3 2 1 と表示されます

#include <stdio.h>

main(){
int i;
int a[] = {1,2,3,4};

for(i = 3; i >= 0; i++)
printf("%d ",a[i]);
printf("\n");

return 0;
}

こうすると、予期せにエラーが出てしまいますが
何故、-を+に変えただけで、こうなってしまうのでしょうか?
ご説明お願い致します、なるべく簡単に・・・・。
0181デフォルトの名無しさん2007/02/05(月) 01:15:51
iが4以上だと配列aの領域を超えてるだろ。
しかも無限ループだし。
0182デフォルトの名無しさん2007/02/05(月) 01:16:35
i=0だろ
0183デフォルトの名無しさん2007/02/05(月) 01:16:37
3に1を足すと4になるからです。
0184デフォルトの名無しさん2007/02/05(月) 01:21:53
では、4だと真になり続けてしまうからでしょうか?
0185デフォルトの名無しさん2007/02/05(月) 01:56:17
>184
a[4]に何が入ってる?
0186デフォルトの名無しさん2007/02/05(月) 01:57:52
無いです
0187デフォルトの名無しさん2007/02/05(月) 02:17:02
質問です
#include <stdio.h>

main(){
int x,y;
int a[2][3] = {
{10,20,30},
{40,50,60}
};
for(x =0; x < 2; x++){
for(y = 0; y < 3 ; y++)
printf("a[%d][%d] = %d",x,y,a[x][y]);
printf("\n");
}
return 0;

}
c:\C>sample1
a[0][0] = 10a[0][1] = 20a[0][2] = 30
a[1][0] = 40a[1][1] = 50a[1][2] = 60

入門書の最初の解説では、int a[2][3]
[2]がyの要素、[3]がxの要素となっていますが
現に上のソースでは、 [2]がxの要素、[3]がy と
なっています、どうして変わっているのでしょうか?
int x,y; こう宣言したからでしょうか?





0188デフォルトの名無しさん2007/02/05(月) 02:22:34
>>187
その入門書の単なる間違えでしょ。
0189デフォルトの名無しさん2007/02/05(月) 02:34:10
これは関係ないでしょ
 int x,y;
 int y,x;

ミスをしたんだな。

xは一般的にx軸のことであり横方向であり、
横1行の処理を終えたら次の行というのが多いパターンであり
配列のメモリ上の並び順は
 a[0][0]
 a[0][1]
 a[0][2]
 a[1][0]
 a[1][1]
 a[1][2]
だから
 a[y][x]
というのが一般的だと思う。

だから(推測だけど)
入門書の説明しているときは、a[y][x]にする予定だった。
でも実際にプログラムを作るときにミスしたんだよ。
01901872007/02/05(月) 03:57:19
>>188
>>189
レス、ありがとうごいます。

>>これは関係ないでしょ
 int x,y;
 int y,x;

ミスをしたんだな。

そうですか・・・・因みに持っている参考書が二つとも
そうなっています・・・・。翔泳社のです。

01911872007/02/05(月) 04:06:57
となると

#include <stdio.h>

main(){
int x,y;
int a[2][3] = {
{10,20,30},
{40,50,60}
};
for(y =0; y < 2; y++){
for(x = 0; x < 3 ; x++)
printf("a[%d][%d] = %d",x,y,a[y][x]);
printf("\n");
}
return 0;

}

c:\C>sample1
a[0][0] = 10a[1][0] = 20a[2][0] = 30
a[0][1] = 40a[1][1] = 50a[2][1] = 60

これが正解でしょうか?

>>>for(y =0; y < 2; y++){
for(x = 0; x < 3 ; x++)
printf("a[%d][%d] = %d",x,y,a[y][x]);

を訂正してみました。
0192デフォルトの名無しさん2007/02/05(月) 08:15:49
×printf("a[%d][%d] = %d",x,y,a[y][x]);
○printf("a[%d][%d] = %d",y,x,a[y][x]);



隙間なく繋がってしまうのもへんだね
以下では
最後にも", "がついてしまうので変だけど

printf("a[%d][%d] = %d, ",y,x,a[y][x]);

a[0][0] = 10, a[0][1] = 20, a[0][2] = 30,
a[1][0] = 40, a[1][1] = 50, a[1][2] = 60,
0193誰か教えてください2007/02/05(月) 16:07:26
自動販売機プログラム
0194デフォルトの名無しさん2007/02/05(月) 16:13:06
>>193
同時押しに対するインターロックとか
つり銭・返却の取り扱いとか
在庫管理とか
(くじ管理)とか
そういうことを期待してるん?
01951872007/02/05(月) 18:09:56
>>192
レス、ありがとうごいます、ですが幾つか疑問点が残ります

#include <stdio.h>

main(){
int x,y;
int a[2][3] = {
{10,20,30},
{40,50,60}
};
for(x =0; x < 2; x++){
for(y = 0; y < 3 ; y++)
printf("a[%d][%d] = %d",x,y,a[x][y]);
printf("\n");
}
return 0;

このソースと

01961872007/02/05(月) 18:15:41
#include <stdio.h>

main(){
int x,y;
int a[2][3] = {
{10,20,30},
{40,50,60}
};
for(y =0; y < 2; y++){
for(x = 0; x < 3 ; x++)
printf("a[%d][%d] = %d ",y,x,a[y][x]);
printf("\n");
}
return 0;

}

このソースの実行結果が
a[0][0] = 10, a[0][1] = 20, a[0][2] = 30,
a[1][0] = 40, a[1][1] = 50, a[1][2] = 60,

と同じになりますが、前者の方のソースは入門書通りにです
そっちの方のソースに誤りがあるんですよね?
これ等のソースで、前者の方だと、yが3、xが2です
後者の訂正ソースだと、yが2、xが3となっています。
こっちが正しいと判断して宜しいでしょうか?
横がx、縦がyなので・・・・

そして、もう一つ質問があります
何故、微妙に違うソースなのに結果が同じになるのでしょうか?
最大の疑問です。
0197デフォルトの名無しさん2007/02/05(月) 18:18:35
>>196
xとyを完全に入れ替えれば(コンパイラにとってxとyを区別する必要がないので)全く同じ振る舞いになる。
>195では外側がxであり、>196では外側がyというだけ。
つまり、配列aの使い方が>195と>196では違っていると言うことになる。
0198デフォルトの名無しさん2007/02/05(月) 18:22:28
>>196
ループを回している順が変わらないから
変数A: [0 .. 2) で配列の先の添え字回し用
 変数B: [0 .. 3) で配列の後ろの添え字回し用

>>195 のソースは 変数Aを x 変数Bを y に
>>196 のソースは 変数Aを y 変数Bを x に
してるだけ
01991972007/02/05(月) 18:24:26
追記:
xに横方向、yに縦方向と言う意味付けをしているのは人間であり、コンパイラはそんなことは頓着しない。
そもそも、Cの配列の配列は所謂二次元配列とは趣が異なるからa[x][y]かa[y][x]かは用途によってまちまちだったりする。
その上、実際によくある応用だと、二次元空間を仮想的に位置次元空間で表わす方法を取ることが多い。
その場合は、こんなコードになるかもしれない。
int main()
{
int a[] = {10, 20, 30, 40, 50, 60};
for (int y = 0; y < 2; ++y) {
for (int x = 0; x < 3; ++x) {
printf("a[%d][%d] = %d", y, x, a[y * 3 + x]);
if (x < 3 - 1) putchar(',');
}
putchar('\n');
}
return 0;
}
02001872007/02/05(月) 18:27:50
ありがとうごいます、とても厄介で難しいですね・・・
では、本の方も間違ってはいないのでしょうか?

>>197
>>>195では外側がxであり、>196では外側がyというだけ。
これだと、配列aの位置が変わり

a[0][0] = 10a[1][0] = 20a[2][0] = 30
a[0][1] = 40a[1][1] = 50a[2][1] = 60
の様に逆にはならないのでしょうか?

>>198
うががg、かなり混乱してしまっています
難しいです。
02011872007/02/05(月) 18:32:47
>>199
こんな難しくも書けるのですね

>>int a[] = {10, 20, 30, 40, 50, 60};

だと、yが1ではないのでしょうか?

0202デフォルトの名無しさん2007/02/05(月) 18:38:28
>>200
int a[2][3];
が 横2 x 縦3 なのか、横3 x 縦2 なのか、C言語においてはどっちにでも取れる。
だから、自分で [横2 x 縦3] か [横3 x 縦2] かを決めて、そのルールに合うように書くしかない。

[横2 x 縦3] の場合表示順は
 横2個続けて表示後改行して次の行へ
となるから for (A=0; A<3; A++) for (B=0; B<2; B++) printf("", a[B][A]) ...
のようになるし、(a[ここは 0〜1までの値][ここは 0〜2までの値])

[横3 x 縦2] の場合表示順は
 横3個続けて表示後改行して次の行へ
となるから for (A=0; A<2; A++) for (B=0; B<3; B++) printf("", a[A][B]) ...
のようになる (a[ここは 0〜1までの値][ここは 0〜2までの値])
0203デフォルトの名無しさん2007/02/05(月) 18:56:21
あれだ、xとyって表現から暫く離れた方がいいよ。
>199が書いているように、xが横だとか縦だとかってのは人間の勝手な押し付けなんだから。
02041872007/02/05(月) 19:29:06
>>202
わかり易いご返答、ありがとうごいます。

>>[横3 x 縦2] の場合表示順は
(a[ここは 0〜2までの値][ここは 0〜1までの値])

ではないのでしょうか?
a[][]の位置は、a[ここは 0〜1までの値][ここは 0〜2までの値]) 様に
位置が既に決まっていると言う事でしょうか?


>>203
そうします。
02051872007/02/05(月) 19:31:40
斜め上な質問ばかり、すんまそです

さっきも本屋で調べてきましたが、これらに関する内容が
載って無く困ります
0206デフォルトの名無しさん2007/02/05(月) 19:45:38
>>204
表示内容として(a[ここは 0〜2までの値][ここは 0〜1までの値])を意味してるのではなくて
配列変数のアクセス範囲を括弧内に書いたつもり

int a[2][3] と宣言している以上 最初の添え字の範囲、次の添え字の範囲は変えようがない と
0207デフォルトの名無しさん2007/02/05(月) 20:11:11
char x = 4,y;

とは、char x1 = 2; char x2 = y; の事ですかね?
0208デフォルトの名無しさん2007/02/05(月) 20:12:58
char x;
char y;
x = 4;
のことです。
0209デフォルトの名無しさん2007/02/05(月) 20:21:59
>>208
サンクスです。
0210日下部です2007/02/05(月) 20:25:06
オレに聞け。
すべてはオレが基本だ。
0211デフォルトの名無しさん2007/02/05(月) 20:32:18
日下部はsageなんて謙虚なことはしないぞ。
0212デフォルトの名無しさん2007/02/05(月) 20:47:37
俺、ここの人たち大好きです。
こんな親切な方々は、何処の板にも存在しません。
何度となく挫折しそうになった俺を救ってくれました。
もし、オマイラがいなきゃ、俺はC言語続いてない。
0213デフォルトの名無しさん2007/02/05(月) 20:53:56
質問なのですが、よろしくお願いします。

ポインタpが有効か否か調べるには、次の様にします。
NULLはポインタ版の「0」の様なものですが、
実は実際の値の0になっています。ですから、理論演算子の手法でも書けます。

pは有効? if(p != NULL)又は if(p)
pは無効? if(p == NULL)又はif(!p)

※参考書抜粋

これで、“pは有効? if(p != NULL)又は if(p)
pは無効? if(p == NULL)又はif(!p)”
の意味を、助言して戴ければ幸いです。
0214デフォルトの名無しさん2007/02/05(月) 20:55:03
>>212
そうですか、よかったね
C言語をある程度マスターしたら、ここでほかの人に教えてあげるといいよ
教えることによっては自分の未熟で不完全な部分がわかってくるものだから
自分のためにもいい
02151872007/02/05(月) 20:56:18
>>206
ありがとうございました。
皆さんのお陰で大体は理解?できました・・・・。
0216デフォルトの名無しさん2007/02/05(月) 20:58:44
>>213
if(p != NULL)又は if(p) は厳密にはヌルポインタかどうかのチェックだね
ポインタが汚れた値が入っている場合はチェックできないね
0217デフォルトの名無しさん2007/02/05(月) 20:58:59
>>214
そうしまふ
0218デフォルトの名無しさん2007/02/05(月) 21:00:34
>>216
ご返答、ありがとうごいます。

“ポインタが汚れた値が入っている場合はチェックできないね ”
とはどういう事なのでしょうか?
0219デフォルトの名無しさん2007/02/05(月) 21:13:33
>>218
*p とやって鼻から悪魔が出るような、でも非NULLなポインタ 
# p=1; とか非0で適当なアドレス(?)を指し示した場合
0220デフォルトの名無しさん2007/02/05(月) 21:14:47
>>218
そのポインタが実際に有効であるかどうかということ
たとえばプログラムがメモリ100番地から200番地の領域を確保したとします
ポインタはメモリの先頭番地をさすので通常なら100になっているわけです
仮に0だったなら 0番地にはメモリ領域を確保できないので実質「確保されたメモリはない」ということが分かります
ところがポインタが300番地をさしていたらどうでしょう?
if( p != NULL) や if(p) としては0で無い以上メモリアドレスを指定していることになりますが
実際には確保されていないアドレス(有効ではないアドレス)ということになります
>>216がおっしゃっているのはこのことです
if( p != NULL) などのコードではポインタが実際に有効か無効であるかは調べようが無いんです
0221デフォルトの名無しさん2007/02/05(月) 21:30:47
>>220
えーーーぇ
ポンタって注意しないと勝手に違うと所を指すことあるんですかー、怖えー
だから、ポインタって難しいのか
0222デフォルトの名無しさん2007/02/05(月) 21:32:13
ポンタってたぬきですか
0223デフォルトの名無しさん2007/02/05(月) 21:36:41
>>213
そこで言っている有効とはポインタがどこか*演算子などを使用して
そのポインタを逆参照(指し示す先を読み書き)できる状態のことだと思えばよい。

CではNULLをどこも指していないポインタ(の値)と定めているので、
逆にポインタ型の変数の値がNULLでなければ、そのポインタ型の変数はどこかの
変数(か何か)を指し示していると見なして処理することが多い。

しかし、>216>219-220の言うとおり実際にはポインタの値はNULLでないが、
逆参照してはならないという状態も存在する。ただしこの状態のポインタを逆参照するのは、
プログラマのミスであり、バグに過ぎないので、通常はNULLかどうかでポインタが有効かどうかの判断に代える。

パソコンなど現代的なOSの下で実行するプログラムでは、NULLなど無効な値を持つポインタを逆参照すると、
不正なメモリアクセスとしてプログラムの実行が停止される。Windowsではおなじみの
一般保護違反や「メモリがread/writtenになることはできませんでした」というダイアログが表示されるし、
Unix/Linux系だとsegmentation faultが表示される。
02242202007/02/05(月) 21:37:54
>>221
いや、ポインタが「勝手に違うと所を指すこと」はないですよ
たとえばポインタの演算の時に間違って違うアドレスをさすような式を書いてしまったとかでしょう
あくまで書いた人のミスです
ポインタを0で初期化するのを忘れたとかもありますね
0225デフォルトの名無しさん2007/02/05(月) 21:41:26
>>224
次点で

int a[3];
int* p = a;
int b[3];

a[3] = 1; とか b[3] =1; とかの配列範囲突破の副作用で p が書き換わる
とかね。
0226デフォルトの名無しさん2007/02/05(月) 22:30:17
unionの初期化について教えてください。

C言語の学習サイトを調べてみると
「共用体の初期化はその最初のメンバの値で行わなければなりません」
とありましたが、絶対に不可能なのでしょうか?

下記のコードの st_hoge.un_point.pshort に
初期化で &s_area[0] を代入する方法があったら教えてください。

/*------------------------------------------------------*/

const short s_area[] = { 1, 2 ,3, 4, 5 };

/* 構造体定義 */
typedef struct _ST_Hoge {
union {
const long* plong;
const short* pshort;
} un_point;
} ST_Hoge;

/* 初期化 */
const ST_Hoge st_hoge = {
??? /* ←ここで un_point.pshort に &s_area[0] を入れたい! */
};
0227デフォルトの名無しさん2007/02/05(月) 22:35:41
言葉足らずでした。

>C言語の学習サイトを調べてみると
>「共用体の初期化はその最初のメンバの値で行わなければなりません」
>とありましたが、絶対に不可能なのでしょうか?
unionの第二のメンバ pshort に初期化で値を入れることが絶対に不可能なのか?
という意味です。
0228デフォルトの名無しさん2007/02/05(月) 22:38:42
その構造体なら、キャストして放り込めばええやん。
0229デフォルトの名無しさん2007/02/05(月) 22:41:28
はいはい。C99、C99。コンパイラがC99に対応してないという文句は却下ね。

const ST_Hoge st_hoge = {
.un_point.pshort = &s_area[0]
};
0230デフォルトの名無しさん2007/02/05(月) 23:25:54
>>228
ポインタのキャストは、今回は無しでお願いします。

>>229
コンパイラがどうというのは、勉強不足で理解できていないですが
C99に対応していないコンパイラでは、最初のメンバ以外には
初期化で値を入れることはできないということですか?

勉強用に使っているbcc5.5.1では
const ST_Hoge st_hoge = {
.un_point.pshort = &s_area[0]
};
はコンパイルエラーでした。
0231デフォルトの名無しさん2007/02/05(月) 23:36:01
C言語のアルゴリズムについての質問なんですが、
「2分木の先行順走査が、レベル順走査のキューより記憶領域を
 多く使うような木の例」
とはどのようなものがあるんですか?
0232デフォルトの名無しさん2007/02/06(火) 00:01:57
>>231
期限:2月7日
を忘れてるぞ
0233デフォルトの名無しさん 2007/02/06(火) 00:06:17
>>230
以下のやり方でソース書いて実行したら一応初期化されてる
けど、unionでconst使うの?
#include <stdio.h>

typedef struct{
union UNI{
const long* plong;
const short* pshort;
}uni;
}ST_Hoge;

int main()
{
int i;
const short s_area[] = { 1, 2 ,3, 4, 5 };
const ST_Hoge st = {(long *)s_area};

for(i = 0; i < 5; i++)
printf("%d ",st.uni.pshort[i]);
putchar('\n');

return 0;
}
0234デフォルトの名無しさん2007/02/06(火) 00:08:35
>>231
ちなみに17:40までだな
0235デフォルトの名無しさん2007/02/06(火) 00:14:53
>>233
>const ST_Hoge st = {(long *)s_area};
ポインタのキャストは
今回は使えないことになっているので。

なぜunionを使うかというと
書いていないですがST_Hoge構造体には他にもメンバがいて、
できるだけ構造体のサイズを小さくしたいので同時に使わないポインタは
unionで纏めたいのです。
0236デフォルトの名無しさん2007/02/06(火) 00:19:31
constを使う理由は、静的なテーブルで
ROM領域にデータを置いておく必要があるので
constで定義しています。
0237デフォルトの名無しさん2007/02/06(火) 00:23:53
>>231
二分木に 1〜10 の順で登録した時にはどうなる?
0238デフォルトの名無しさん2007/02/06(火) 00:23:58
なんでキャストしたらあかんの?
0239デフォルトの名無しさん2007/02/06(火) 00:27:57
unionで纏められるのがポインタなら、先頭をconst void*にでも
しとけば。キャストは暗黙で済んじゃうから。
0240デフォルトの名無しさん 2007/02/06(火) 00:32:55
>>230
アラインメントは分かってる?
0241デフォルトの名無しさん2007/02/06(火) 00:34:57
>>226
何かconstの用法間違ってる気がする...、unionメンバのconst要らんように思うが
ま、何したいのか、良くわからんのでなんとも言えんが
ST_Hoge st_hoge 変数で、ROM内の定数のアドレスを共有出来るようにしたいってこと?
0242デフォルトの名無しさん2007/02/06(火) 00:57:58
>>238
>>239
ポインタのキャストはできません。
コーディング規約で縛られているので。

>>240
わかっていないと思います。
4byteバウンダリのことですか?

>>241
>>226のグローバルの定義があって、その後に
void main() {
int i;
for( i=0; i < 5; ++i )
printf("st_hoge.un_point.pshort[%d] = %d\n", i, st_hoge.un_point.pshort[i]);
                    ~~~~~~
                    ↑pshortでアクセスすることが大事
}
で1, 2, 3, 4, 5と正確にアクセスしたいです。
0243デフォルトの名無しさん2007/02/06(火) 03:07:46
>>242 これじゃだめあるか?
#include <stdio.h>
const long l_area[] = { 100, 200, 300, 400, 500};
const short s_area[] = { 1, 2 ,3, 4, 5 };

/* 構造体定義 */
typedef struct _ST_Hoge {
union {
const long *pLong;
const short *pShort;
} un_point;
} ST_Hoge;

int main()
{
int i;
ST_Hoge st;
st.un_point.pShort = &s_area[0];

for(i = 0; i < 5; i++)
printf("%d ",st.un_point.pShort[i]);
putchar('\n');

st.un_point.pLong = &l_area[0];
for(i = 0; i < 5; i++)
printf("%d ",st.un_point.pLong[i]);
putchar('\n');

return 0;
}
0244デフォルトの名無しさん2007/02/06(火) 03:23:54
>>243
組み込みでROM領域ってことは代入はできないと思うんだ
0245デフォルトの名無しさん2007/02/06(火) 03:32:37
コーディング規約で縛られているプログラムの面倒は見ません。
0246デフォルトの名無しさん2007/02/06(火) 03:37:39
えっ、代入できないあるって
st.un_point.pShort = &s_area[0];
これ駄目あるか、ROMの扱いって難しいあるね
0247デフォルトの名無しさん2007/02/06(火) 04:15:51
そういや何で中国人?って〜あるって使うイメージなんだろ?
0248デフォルトの名無しさん2007/02/06(火) 06:08:00
早上好!
老師、const ST_Hoge st_hoge、 このconst何のためにあるニダ?
中国3万年の歴史をもってしても不明あるニダ
>>242 努力加油!
0249デフォルトの名無しさん2007/02/06(火) 06:47:47
へ〜
0250デフォルトの名無しさん2007/02/06(火) 07:24:49
まとめ。
1.コーディング規約を無視してキャストする。
2.暗黙のキャストは許可されると解釈して、
 const void *を共用体の先頭にもってくる。
 というか暗黙のキャストが不可なら、void*は使えないってことか?
3.コンパイラをC99対応のものに換えて、>229
4.諦める
0251デフォルトの名無しさん2007/02/06(火) 07:30:40
>247
多分漫画か何かでキャラ作りの為に中国人キャラがそう喋ってたんだろ
んで在日中国人でそれを真似る奴も現れた
本場の中国人が日本語覚えたてだとアグネスみたいになる

>248
一瞬、素が出ててヮロタw
0252デフォルトの名無しさん2007/02/06(火) 07:32:54
満州帝国由来だときいた。

>247
http://ja.wikipedia.org/wiki/%E5%8D%94%E5%92%8C%E8%AA%9E
■ このスレッドは過去ログ倉庫に格納されています