C++配列の型に関するC++規格について教えてください

このQ&Aのポイント
  • C++配列の型に関するC++規格について、配列を関数に渡す際の型保証について解説します。
  • ポインタで配列を渡す方法と、配列の参照渡しの方法についても述べます。
  • std::fill_n()関数に関する警告メッセージやその対処方法についても言及します。
回答を見る
  • ベストアンサー

C++配列の型に関するC++規格について教えていただきたいです。

C++配列の型に関するC++規格について教えていただきたいです。 以前にYahoo知恵袋でも質問しましたが、答えが得られませんでしたので、こちらでも質問させていただきたいと思います。 ※以下、質問になります。(分かり難いかも知れませんが宜しくお願い致します。) 環境は、Visual Studio 2010 (C++) です。 std::fill_n() で次のような警告がでましたので、調べていましたところ、 ...\xutility(2801): warning C4996: 'std::_Fill_n': Function call with parameters that may be unsafe - ... 次のような定義方法を見つけました、 typedef char (&std::tr1::_No)[1]; ↑このような定義方法があることを初めて知りました。 ちなみに、std::fill_n() は次のようになりました。 long data[32]; std::fill_n(data, 32, 0); ←正常 long* p_data = data; std::fill_n(p_data, 32, 0); ←warning long (&a_data)[32] = data; std::fill_n(a_data, 32, 0); ←正常 知りたいのは、配列を関数に渡すときに、 通常は、void func(long* pd); のようにポインタで渡すと思います。 また、void func(long pd[]); や void func(long pd[32]); もポインタの場合と同じになりますが、型保証がありません。 これはC++規格で規定されていることだと思います。 次のようにすると、型保証がされますが、この記法がC++の規格として規定されているかを知りたいです。 1. void func(long (&ad)[32]); // 関数呼び出しは、func(data); 2. void func(long (*pd)[32]); // 関数呼び出しは、func(&data); また、通常のポインタで配列を渡すことを、配列の参照渡し?と言うと思いますが、 この1,2,は何渡し?と言われるのでしょうか? #長い文になって申し訳ありませんが、宜しくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

> 次のようにすると、型保証がされますが、この記法がC++の規格として規定されているかを知りたいです。 > 1. void func(long (&ad)[32]); // 関数呼び出しは、func(data); > 2. void func(long (*pd)[32]); // 関数呼び出しは、func(&data); 規定されています。 > また、通常のポインタで配列を渡すことを、配列の参照渡し?と言うと思いますが、 それは便宜的な表現です。 言語仕様上はあくまでも値渡しです。 > この1,2,は何渡し?と言われるのでしょうか? 1.は参照渡しですが、2.は(ポインタの)値渡しです。

mi65536
質問者

お礼

明確な答えをしていただきましてありがとう御座います。 やっとスッキリしました。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

ばっさりいってしまうと, 1, 2 ともちゃんとある. というか, 2 については C++ 以前に C にもあるんだが. 以下余談: long data[32]; と定義されているとしましょう. このとき, 次の式 *(data + 3) = 7; における「data の型」は何だと思いますか?

mi65536
質問者

お礼

回答して頂き、ありがとう御座います。 > *(data + 3) = 7 data+3 ← longポインタ型だと思っていました。違うんでしょうか? *(data+3) ←long型?? Cにも規定されていたんですね。 「ANSI C/C++ 辞典 (平林雅英著) (1997/3版)」には記述が見つけられませんでしたので、 てっきりCにはないものと思い込んでいました。

関連するQ&A

  • void*型の配列について

    void* a[2]; void* b = a; void* c[2] = (void *[2])b; error C2440: '型キャスト' : 'void *' から 'void *[2]' に変換できません。 配列型への変換はありませんが、参照またはポインタから配列への変換があります。 void*型にした a を再度void*型の配列に戻すにはどのように記述すればよいでしょうか? 環境はXP(SP3)のVS2008 MFC です。 宜しくお願いいたします。

  • 配列の受け渡し

    全く原因が分からないので質問させていただきます. 次のようなプログラムがあります. メイン関数で配列を宣言して, これを関数funcに渡して,func内で処理を行う. その後,メイン関数でprintf()を使って配列の内容を表示させる. 私の書いたソースは次のようになっています. int main(void) { double data[]={1.0, 2.0, 3.0, 4.0}; for(i=0; i<4; i++) { printf("%f\n", data[i]); } func(data, 4); for(i=0; i<4; i++) { printf("%f\n", data[i]); } } void func(double *f, int n) { 配列に処理を行う } メイン関数の中で, 一つ目のprintf()はちゃんと配列dataの初期値を表示します. ところが,二つ目のprintf()の手前で, 「例外」とエラーがでてきます. (コンパイルは通っています.) これが何故なのか,さっぱり分かりません. 関数func()の最後にprintf()を書いてみたところ, ちゃんと処理を行った後の正しい値が表示されます. なので,関数func()自体にバグはないように思うのです. 原因が分かる方,いらっしゃいましたら, どうぞよろしくお願いします.

  • 【C++】関数ポインタの代入

    C++の関数ポインタについて質問です。 下記のように関数ポインタを宣言し、3通りの代入を行ってみました。 (3)のように関数名の頭に&を付けた場合と(2)のように&を付けなかった場合で 全く動きが同じになってしまうのですが、何故なのでしょうか? ------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; void Func1(){ cout<<"Func1が呼ばれました。"<<endl; return; } int main() { //(1) void (*fp1_1)(); fp1_1 = Func1; fp1_1(); //(2) void (*fp1_2)()=Func1; fp1_2(); //(3) void (*fp1_3)()=&Func1; fp1_3(); getchar(); return 0; }

  • C言語の型と配列

    char* str[10]={"a","b"}; char* str2="c"; としたときにstr=str2とすると 型が合わないといったエラーが出ます。 でもstrって結局はポインタの配列の先頭要素のアドレスですよね。 ポインタにポインタを入れているので通るのかなと思ったんですけど、 配列で宣言するとポインタにも型がつくのでしょうか? この例だと strは char * を10個持つ配列をさすポインタ  で、 str2はchar *をさすポインタ みたいなかんじです。 質問の意味がわかりにくいですが、ご指摘をいただければ補足しますので よろしくお願いします。

  • c言語 配列

    関数の中で複数の値を配列で返したいのですが,どうすればいいでしょう? 配列を関数に渡す時にはアドレスが渡されるので,ポインタと同様関数内で値を変えればmain関数の値も変わるのではないかと思ったのですが,上手くいきません. 知りたいのは,main関数の中の配列(できれば2次元配列)の値を他の関数から値を変更する方法です.下のプログラムはためしに書いてみたものです.質問を理解するうえで役立てば幸いです. #include<stdio.h> void func(double aaa[][3] ,double bbb[]); void main(void){ double array_a[3][3]={{1,2,3},{4,5,6},{7,8,9}}; double array_b[3]={0}; func(array_a,array_b); } void func(double aaa[][3] ,double bbb[]) { int i,j; for (i=0;i<3;i++) { for (j=0;j<3;j++) { bbb[i]=bbb[i]+aaa[i][j]; } } }

  • 配列

    適当な記述ですが、次を見てください。 void roll(int *c) { int n, b2[8]; if(t<3) { for(n=0; n<8; n++) b2[n]=c[n]; for(n=0; n<8; n++) c[b2[n]]=7-n; for(n=0; n<8; n++) printf("%d",c[n]); printf("\n"); t++; roll(c); } else t=0; } int main() { int b[]={3,6,4,0,7,2,5,1}; roll(b); for(n=0; n<8; n++) printf("%d",b[n]); //36407251が表示されるようにしたい。 return(0); } rollが何の関数かは省略しますが、rollにmainのb(ポインタ?)を渡し、ある処理をして,それでmainに戻ってきた時にb[]を表示すると、36407251が表示されません。 ポインタを引数にするってことはポインタでさしてるとこをrollで操作してるわけですよね? そうすれば変わって当然だとはおもいます。 でも関数1で関数2に配列1を渡し、その関数2の中でで配列1の値が変化しても、元の関数1にもどれば配列1のまま変化していないようにするにはどうすればいいですか? やはり もう1つ配列を用意しなきゃだめなのでしょうか。

  • C言語で、他の関数で配列を書き換えられないようにしたい

    下のCのプログラムでは、func関数は配列aの先頭要素へのポインタを返します。 main関数の側では配列aの中身を表示します。 しかし、main関数のfor文の中の★の部分をコメントアウトせずに入れると、この配列の中身が書き換わってしまいます。  私はfunc関数以外では、この配列の中身をいじられたくないのです。  なんとかfunc関数を工夫して作成して、func関数以外では、配列の中身が変わらないようにしたいのですが、どうすればよいでしょうか。    とは言ったものの、多分できないだろうなあ、という気がします。  できないならばできないでも仕方ないのですが、確信が持てないのです。 条件があります。 funcでは表示は行なわない。 配列aの中身を表示できるように、funcから呼び出し元へ、aのアドレスまたはaの先頭要素のアドレスがわかるような情報を返す。 #include <stdio.h> char *func(int i) { static char a[]="AAAA"; a[i]='z'; return a; } int main(void) { int i; for(i=0; i<4; i++) { char *p=func(i); /* p[i]='X'; ★配列の中身を書き換えてしまう。 */ puts(p); } return 0; }

  • 引数で指定された配列の要素数の取得

    どうもこんにちは。 C言語でプログラムを作成しています。 ある関数に配列を渡すことを考えていますが、渡した配列の要素数を取得する方法は何かありますか? 標準の関数を見ても、配列の先頭アドレスのポインタとともに、配列の要素数を渡しているものばかりで、配列のポインタを渡しているものは見かけません。 要素数があらかじめわかっていれば、それを引数の型に指定できますが、呼び出されるまで不明な場合はうまくいきません。 配列の要素数も引数として一緒に渡す必要がありますか? [作ってみたサンプル] #include <stdio.h> #include <stdlib.h> #include <string.h> // func1 と func2 をまとめられないだろうか。。。 void func1(int (*p)[10]) { ________int n = sizeof(*p) / sizeof((*p)[0]); ________int i; ________for (i = 0; i < n; i++) { ________________printf("%d\n", (*p)[i]); ________} ________printf("\n"); } void func2(int (*p)[5]) { ________int n = sizeof(*p) / sizeof((*p)[0]); ________int i; ________for (i = 0; i < n; i++) { ________________printf("%d\n", (*p)[i]); ________} ________printf("\n"); } int main(int argc, char *argv[]) { ________int ary1[10] = { 2, 4, 6, 8, 0, 1, 3, 5, 7, 9 }; ________int ary2[5] = { 3, 6, 9, 12, 15 }; ________func1(&ary1); ________func2(&ary2); ________return 0; }

  • Voidポインタで受け取った変数の型を調べる方法

    あるライブラリの関数を利用しようとしたのですが、その関数の引数にVoidポインタがあり、どういう型のデータを格納したのかわかりません。このポインタのアドレスに格納されたデータの型を調べる関数なり方法なりというのはあるのでしょうか。 Voidポインタというのは型を問わずに受け取れるというのは利点ですが、受け取ったものがあらかじめなんだかわからない場合はどうするのでしょうか。よろしくお願いします。

  • ポインタを使って構造体の配列を戻り値にするには

    関数の戻り値を構造体の配列(アドレスを受け渡しを利用して)にしたいのですがうまくゆきません。 以下のプログラムではコンパイルはできるのですが、 a0 = 2 a1 = 4198512 a2 = 4329332 と表示されてしまいa1,a2がうまくゆきません。 ********************************************* #include<stdio.h> struct test{ int a; }; struct test *func(void); void main(void) { struct test *data;//構造体ポインタ int i; data = func(); //ポインタにtest関数の戻り値(アドレス)を代入 for(i=0;i<=2;i++){   printf("a%d = %d\n",i,(data+i)->a); //構造体要素を表示 } } struct test *func(void) { struct test data[3]={1,2,3}; //構造体配列を定義 return (&data[0]); //構造体配列の先頭アドレスを返す } ************************************************* test関数から受ける取ったアドレス(&data[0])をポインタ(data)に代入して1づつずらして表示させれば a0=1,a1=2,a=3 となると思ったのですがどこが間違っているのでしょうか? よろしくお願いします。

専門家に質問してみよう