• 締切済み

配列の長さについて

現在課題で書いているプログラムに以下のような関数があるのですが、 unsigned char key[32]; int w[60]; int data[NB]; int nk; int nr; int data2[32]; int Cipher(int *); int invCipher(int *); void encryptEBC(int *); void decryptEBC(int *); main(){ unsigned char keys[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; unsigned char iv[]={0xcb,0x70,0x05,0x9e,0x27,0x2f,0x4e,0xd2, 0xd0,0xbe,0x0b,0x06,0xbf,0x16,0xec,0x5a}; unsigned char init2[]={'1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0', '1','2','3','4','5','6','7','8','9','0',0x0a}; //unsigned char init2[]={'h','e','l','l','o'}; int isize = sizeof(init2)/sizeof(init2[0]); int dsize2 = sizeof(data2)/sizeof(data2[0]); printf("%d,%d\n",isize,dsize2); FILE *fp; char *fname = "test.txt"; unsigned char init[16]; int i = 0; int c; fp = fopen( fname, "r" ); if( fp == NULL ){ printf( "%sファイルが開けません\n", fname ); return -1; } while( (c = fgetc( fp )) != EOF ){ init[i] = c; i = i+1; } fclose( fp ); memcpy(key,keys,16); nk = 4; nr = nk + 6; KeyExpansion(key); memcpy(data,init,16); memcpy(data2,init2,isize); printf("%d\n",dsize2); datadump("PLAINTEXT: ",data,16); datadump("KEY: ",key,16); Cipher(data); datadump("Cipher: ",data,16); invCipher(data); datadump("invCipher: ",data,16); printf("\n"); printf("%d\n",dsize2); datadump("PLAINTEXT: ",data2,dsize2); encryptEBC(data2); printf("%d\n",dsize2); datadump("EBCCipher: ",data2,dsize2); decryptEBC(data2); datadump("invCipher: ",data2,dsize2); printf("\n"); return 0; } void encryptEBC(int data[]){ int dsize = sizeof(data)/sizeof(data[0]); int tmp[16]; int i,j,k; printf("%d\n",dsize); KeyExpansion(key); for (i = 0; i < dsize; i += 16) { for (j = 0; j < 16; j++){ tmp[j] = data[i + j]; } Cipher(tmp); for(k=0;k<16;k++){ data[i+k] = tmp[k]; } } } 関数encryptEBC内のdsizeの値がこの場合だとmain内の配列data2の長さ32になってほしいのですが、1になってしまいます。 非常に見ずらいプログラムで申し訳ないのですが、どなたか1になってしまう理由、またどうすれば正しくdata2の長さを求められるか教えていただけないでしょうか?

みんなの回答

回答No.3

補足すると sizeof() は関数ではなく演算子で 実行時ではなくコンパイル時に評価されるため 動的に長さは取れないのです。

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

本題じゃないけど.... 「main内の配列data2の長さ32になってほしい」って書いてあるけど, data2 って配列は main の中にはないよねぇ. あと, 3回使ってる memcpy のうち最初の 2回で定数をベタに書いてある理由がよくわからない. sizeof とかを使ってあげようと思ってもいいんじゃないかな. ついでに最後の memcpy で使っている isize も (値は正しいけど) 意味は間違ってる気がする.

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.1

関数の仮引数として int f(int[] a) と書いてもそれは int f(int *a) と解釈されます。つまり関数内で sizeof(a) としたら、たとえ a が関数の呼び出し元では配列であってもポインタのサイズを返します。 どうしても配列のサイズを関数内で知りたいならば、別の引数でサイズを渡しましょう。 それが嫌なら、 ・データに絶対出ない値があるなら文字列のようにデータの最後の値を取り決めておく ・この関数は与えられたポインタに規定の長さがある領域を指す必要があると明言して利用者にそれを厳守させる ・渡す配列が int の場合のみ限定の手段として 1 個めのデータはデータ長を表すと明言して利用者にそういうデータを作らせる という手もあります。まあたぶん今回の場合は上記の 1 番目はダメで 2, 3 番目は利用者が不便なので素直にサイズを別変数で渡すべきだと思いますが。

参考URL:
http://www.kouno.jp/home/c_faq/c6.html#4

関連するQ&A

  • 暗号利用モードの実装

    C言語でAESのEBCモードを実装しようとしています。 unsigned char key[32]; int w[60]; int data[NB]; int nk; int nr; int data2[32]; int Cipher(int *); int invCipher(int *); void encryptEBC(int *,int n); void decryptEBC(int *,int n); main(){ unsigned char keys[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; unsigned char iv[]={0xcb,0x70,0x05,0x9e,0x27,0x2f,0x4e,0xd2, 0xd0,0xbe,0x0b,0x06,0xbf,0x16,0xec,0x5a}; unsigned char init2[]={'1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0', '1','2','3','4','5','6','7','8','9','0',0x0a}; int isize = sizeof(init2)/sizeof(init2[0]); int dsize2 = sizeof(data2)/sizeof(data2[0]); printf("%d,%d\n",isize,dsize2); FILE *fp; char *fname = "test.txt"; unsigned char init[16]; int i = 0; int c; fp = fopen( fname, "r" ); if( fp == NULL ){ printf( "%sファイルが開けません\n", fname ); return -1; } while( (c = fgetc( fp )) != EOF ){ init[i] = c; i = i+1; } fclose( fp ); memcpy(key,keys,16); nk = 4; nr = nk + 6; KeyExpansion(key); memcpy(data,init,16); memcpy(data2,init2,isize); datadump("PLAINTEXT: ",data,16); datadump("KEY: ",key,16); Cipher(data); datadump("Cipher: ",data,16); invCipher(data); datadump("invCipher: ",data,16); printf("\n"); datadump("PLAINTEXT: ",data2,dsize2); encryptEBC(data2,dsize2); datadump("EBCCipher: ",data2,dsize2); decryptEBC(data2,dsize2); datadump("invCipher: ",data2,dsize2); printf("\n"); return 0; } void encryptEBC(int data[],int dsize){ int tmp[16]; int i,j,k; printf("aiu%d\n",dsize); KeyExpansion(key); for (i = 0; i < dsize; i += 16) { memcpy(tmp,&data[i],16); Cipher(tmp); memcpy(&data[i],tmp,16); } } void decryptEBC(int data[],int dsize){ int tmp[16]; int i,j,k; printf("eo%d\n",dsize); KeyExpansion(key); for (i = 0; i < dsize; i += 16) { memcpy(tmp,&data[i],16); invCipher(tmp); memcpy(&data[i],tmp,16); } } このようなプログラムでとりあえず2ブロック分の暗号化、復号を行おうと思っているのですが、1ブロック目しか行えません。 どなたかどこが悪いのかご教授いただけないでしょうか?

  • ポインタと配列

    次のソースで、結果表示でポインタを使いたいのですが、うまくいきません。1件しか表示されないのです。 ポインタの扱いがおかしいのだと思いますが、どうしたらよいでしょうか? #include <stdio.h> #include <string.h> int search(char key[256],FILE *fp,char *result[256][256]); main(void) { FILE *fp; int rep,n,i; char x[256],key[256],*result[256][256]; printf("検索キーワードを入力してください。\n" "キーワード>"); gets(key); if((fp=fopen("personal.txt","r"))==NULL) { printf("ファイルをオープンできません\n"); exit(1); } printf("=====検索結果=====\n"); n=search(key,fp,result); for(i=0;i<n;i++) { printf("%s\n",result[i]); } printf("検索結果:%d件です。\n",n); fclose(fp); } int search(char key[256],FILE *fp,char *result[256][256]) { int n=0; char *p,word[256],*name; while((p=fgets(word,256,fp))!=NULL) { if(strstr(word,key)!=NULL) { name=strtok(p," "); strcpy(result[n],name); n++; } } return n; } 実行すると、下の警告がでます。 illegal pointer combination(param)

  • 漢字を配列に入れたいのですが

    漢字を配列に入れたいのですが、うまくいきません。 3列、60行のcsvファイルを読み込んで配列に入れようをしているのですが、1列目、2列目、3列目にある漢字をそれぞれ配列に入れようとしているのですが、出力するとうまくいかないんです。誰か教えてください。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXBUFFSIZE 256 #define MAXWORDS 15 int split(char* words[], int length, char* split_ch,char* str){ int i,j; for(i=0;i<length;i++){ if((words[i] = strtok(str,split_ch))==NULL)break; str=NULL; } return(i); } int main(int argc, char* argv[]){ if(argc !=2){ printf("入力エラー"); return(0); } FILE *fp; char *ll, *words[MAXWORDS], ch, buff[MAXBUFFSIZE]; int i,j; unsigned int data1[60], data2[60], data3[60]; if((fp =fopen(argv[1],"r"))==NULL){ printf("ファイルが開けません。\n"); } j=0; ll= fgets(buff,MAXBUFFSIZE,fp); while((ll= fgets(buff,MAXBUFFSIZE,fp)) != NULL){ split(words, MAXWORDS, ",",ll); data1[j] = words[0]; data2[j] = words[1]; data3[j] = words[2]; j++; } printf("%s\n%s\n%s\n", data1,data2,data3); }

  • 画像を読み込む配列の確保。

    C言語について質問です。 画像を読み込む時、その画像の幅、高さを入力し、そのサイズに見合った配列を確保します。その後ファイル名を入力し、配列に読み込むプログラムを作成しました。 メインの部分のみ記述します。 int xsize, ysize, i; unsigned char **src; char filename[30]; FILE *fp; printf("ファイル名を入力してください:"); scanf("%s", filename); printf("画像の幅:");scanf("%d", &xsize); printf("画像の高さ:");scanf("%d", &ysize); src = (unsigned char **)malloc(sizeof(unsigned char *) * ysize); for(i=0; i<ysize; i++) src[i] = (unsigned char *)malloc(sizeof(unsigned char) * xsize); fp = fopen(filename, "rb"); fread(src[0], sizeof(unsigned char), xsize * ysize, fp); このように記述し、エラーもなく実行できたのですが、srcをこのまま出力すると変?な画像となって出力されてしまいました。 上のように記述した場合、矛盾する場所はあるでしょうか? そして、この方法以外に配列を確保する方法はあるでしょうか?

  • 配列のサイズ変更

    FILE *fp; char *fname = "test.txt"; unsigned char init[300]; int i = 0; int c; fp = fopen( fname, "r" ); if( fp == NULL ){ printf( "%sファイルが開けません\n", fname ); return -1; } while( (c = fgetc( fp )) != EOF ){ init[i] = c; i = i+1; } fclose( fp ); 自分のプログラムの中のこのようなテキストから文字を読んで配列に格納するような動作の中で、initを大きめにとっておいて配列に格納し終わったら余った空の配列を削除する、という機能を拡張したいのですがどのようにすればいいかわかりません。 どなたか教えていただけないでしょうか?

  • C言語でファイル読み書きを早くしたい。

    いつも利用させてもらって助かっています。 あるプログラムを作成しているのですが、ファイル入力の部分がネックとなってしまって、全体が使いものにならない状況に陥っています。 たくさんのデータをfread1回で読み込むことにより、読み込み速度はずいぶんと改善されましたが、まだ圧倒的に遅い状況です。システムコールを使いましたが、ほとんど改善されませんでした。 読み込み/書き込みの速度を改善する方法として,SSDメモリを使ったりする方法があると思いますが,プログラムの観点から改善できるところはないでしょうか? 下に、ファイル読み込みの部分だけ記述したコードを添付させて頂いたので、改善できる点があれば、御指摘頂けると助かります。 なお、前提として, (1)データはスタック領域だと不足するので、ヒープ領域に確保 (2)データファイルは改行無しの一連のデータ とします。 ちなみに、環境は OS   : CentOS5.3 memory   : 6GB コンパイラ : gcc です。 よろしくお願いします。 //----------------------------------------------------- //通常バージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; FILE *fp; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } fp = fopen("filein.dat", "rb"); fread( data, sizeof( unsigned char), (int)SIZE, fp ); fclose(fp); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; } //----------------------------------------------------- //readシステムコールを使ったバージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } int fd; fd = open( "filein.dat" ); read( fd, data, sizeof(unsigned char)*SIZE); close(fd); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ FILE *fp; fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; }

  • カラー画像からグレースケール画像フォーマットの変換

    カラー画像からグレースケール画像フォーマットの変換するプログラムなんですが、いまいち理解できていません。 プログラムはRGB構造体を使ってのものなんですが添削お願いいたします。 #include<stdio.h> #include<stdlib.h> typedef struct _RGB { unsigned char r; unsigned char g; unsigned char b; } RGB; int main(int argc, char *argv[]) { int x, y; unsigned char *in, *out; int i, j, Magic, level; unsigned char tmp[255]; RGB **pixels; int width = 255; int height = 255; int size = width * height; FILE *fin, *fout; if(argc != 3){ printf("Usage : %s input outpu \n", argv[0]); exit(1); } fin = fopen(argv[1], "rb"); fgets(tmp, 255, fin); if(tmp[0] != 'P'){ return 0; } sscanf(tmp, "P%d", &Magic); if(Magic < 1 || Magic > 6){ return 0; } do{ fgets(tmp, 255, fin); } while(tmp[0] == '#'); sscanf(tmp, "%d %d", &x, &y); if(x < 1 || y < 1){ return 0; } fgets(tmp, 255, fin); sscanf(tmp, "%d", &level); printf("P%d\n", &Magic); printf("%d %d\n", x, y); printf("%d\n", level); in = (unsigned char *)malloc(sizeof(unsigned char) *x*y); fread(in, sizeof(unsigned char), x*y, fin); pixels = (RGB**)malloc(width*sizeof(RGB*)); pixels[0] = (RGB* )malloc(size * sizeof(RGB)); for(i = 1; i < width; i++){ pixels[i] = pixels[i - 1] + height; } free(pixels[0]); for(i = 1; i < width * height * 3; i++){ out[i] = pixels[i][0].r * 0.299 + pixels[i][1].g * 0.587 + pixels[i][2].b * 0.114; } fout = fopen(argv[2], "wb"); fprintf(fout,"P%d\n",Magic); fprintf(fout,"# My new PGM\n"); fprintf(fout,"%d %d\n",x, y); fprintf(fout,"%d\n",level); fwrite(out, sizeof(unsigned char),x*y, fout); free(pixels); free(in); free(out); free(fin); free(fout); }

  • char型+char型ってint型? if(char型==int型)?

    C言語の「汎整数拡張(インテグラルプロモーション)」というものに関するものだと思います。 char型とchar型を加えた結果は、char型でしょうか。それともint型でしょうか。 (下のプログラムの printf("sizeof(a[0]+a[1])は%d\n", sizeof(a[0]+a[1])); /* char型+char型 */ という部分の結果は4なので、int型と考えるべきなのかな。) 私は、char型とint型の加算の結果はint型だと思っていましたが、 char型とchar型の加算の結果はやはりchar型だと思っていました。 (それが間違えているのでしょうか。) if(a[0]==i) /* char型とint型の比較(?) */ の部分では、左辺はchar型、右辺はint型ですが、このように型の違う変数を比較しても文法上構わないのでしょうか。 (私は、「比較は必ず型の同じもの同士でしかできない」と思っていました。) 左辺はchar型のように見えて、じつはint型ですか。 #include <stdio.h> int main(void) { char a[4]; int i=77; printf("sizeof(int)は%d\n", sizeof(int)); printf("sizeof(char)は%d\n", sizeof(char)); printf("sizeof('M')は%d\n", sizeof('M')); printf("sizeof(a[0])は%d\n", sizeof(a[0])); a[0]='M'; a[1]=7+6; a[2]=a[0]+a[1]; printf("sizeof(a[0]+a[1])は%d\n", sizeof(a[0]+a[1])); /* char型+char型 */ printf("sizeof(+a[0])=%d\n", sizeof(+a[0])); if(a[0]==i) /* char型とint型の比較(?) */ puts("a[0]==i"); else puts("a[0]!=i"); return(0); } ちなみにワーニングもエラーもなんにもでません。

  • プログラム(C)

    #include <stdio.h> #include <stdlib.h> #define FNAME "smp.bmp" #define WSIZE 256 #define HSIZE 256 #define BSIZE 1024 int main(void) { struct BMPFILEHEADER { ・   ・ }; struct BMPINFOHEADER { ・   ・ }; unsigned char img[HSIZE][WSIZE][3]; unsigned char buf[BSIZE]; struct BMPFILEHEADER lpHead; struct BMPINFOHEADER lpInfo; FILE *fp; int i; int j; int k; fp = fopen(FNAME,"rb"); if (fp==NULL) { printf("ファイルをオープンできません\n"); return 0; } fread(&lpHead.bfType, sizeof(unsigned short),1,fp); fread(&lpHead.bfSize, sizeof(unsigned int),1,fp); fread(&lpHead.bfReserved1, sizeof(unsigned short),1,fp); fread(&lpHead.bfReserved2, sizeof(unsigned short),1,fp); fread(&lpHead.bf0ffBits, sizeof(unsigned int),1,fp); fread(&lpInfo, sizeof(struct BMPINFOHEADER),1,fp); for(i=0;i<HSIZE;i++) { fread(buf,sizeof(unsigned char),WSIZE*3,fp); for(j=0;j<WSIZE;j++) { for(k=0;k<3;k++) { img[HSIZE-1-i][j][k]=buf[j*3+k]; } } } fclose; return 0; } このプログラムはBMP画像を読み込むプログラムなんですが このプログラムに画素値を出力するプログラムにしたいのですがうまくできません。 結果は(真っ白な画像の時)255255255・・・255255と出力したいのです。白黒画像なのでR=G=Bで1画素値は255だけでいいのですが。どうしても255255255や25500などとでてしまいます。 アドバイスお願いします。(800字までなので構造体の宣言は抜いてしましました) 。

  • 関数先にて配列の長さを取得する方法

    関数にて、引数にて渡された配列(ポインタ)から配列数を調べる方法はないでしょうか? #include <stdio.h> void test(unsigned int *p){ printf ("%d\n", sizeof(*p)/sizeof(p[0])); //結果 1 } int main(){ unsigned int hoge[] = {0x30, 0x31,0x32}; test(hoge); printf("%d", sizeof(hoge)/sizeof(hoge[0])); //結果3 return 1; } 上記コードの関数testの*pから配列の数3が抜き取りたいと思っております。 よろしくお願いします。

専門家に質問してみよう