Visual Cのstat構造体の動作について

このQ&Aのポイント
  • stat構造体をprintf系の関数で出力するとき、Visual Cでは二つ目の変数が正常に出力できない現象が発生します。
  • stat構造体のtime_t型変数をprintf系関数で出力する場合、その変数以降に続けて出力する他の変数が正常に出力できなくなることがあります。
  • printfの書式通りに出力されないだけで、変数の中身は壊れていません。この現象は、Visual Studio 2012および2013のVisual Cで発生します。
回答を見る
  • ベストアンサー

Visual Cのstat構造体の動作

はじめまして。 stat構造体をprintf系の関数で出力するときの異常動作で悩んでいます。 stat関数で読み取った複数のstat構造体の日付情報をprintf関数で 出力書式を"%d %d \n"のように連続して出力するとvisual Cだけ、 二つ目の変数が期待した通りに出力できないのでソースをいじって どのような状態で出力できないのか確認したところ、 Visual studio 2012,2013のvisual Cに於いては、 stat構造体の time_t型変数をprintf系関数で出力する場合、その変数以降に 続けて出力する他の変数が正常に出力できなくなることに 気づきました。これはなぜでしょう? 以下のC言語のソースの例では、先にstring変数を出力してstat構造体の time_t型変数を出力した場合(debug2)には問題ないのに、 変数の出力順を入れ替えるとVisual Cではtime_t型変数以降は 正常に出力できません。(debug3) 尚、time_t変数のst_mtime、st_ctime共、同様の結果になります。 printfの書式通りに出力されないだけで、変数の中身は壊れていません。 // 以下サンプルソース wsttes.c #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/stat.h> #ifdef _HPUX_SOURCE //HP-UXのansi-Cでもコンパイルできるように #define _stat stat #endif int main() { char s1[100]; // s1 struct _stat t1; // t1 strcpy(s1,"testA"); t1.st_atime=111111; // stat構造体を変数として利用しているだけ printf("debug0 s1=%s\n",s1); printf("debug1 t1=%d\n",t1.st_atime); printf("debug2 s1=%s t1=%d\n",s1,t1.st_atime); printf("debug3 t1=%d s1=%s\n",t1.st_atime,s1); return 0; } /*実行結果 Borland C(BCC32) d:\users\work\bc>wsttes debug0 s1=testA debug1 t1=111111 debug2 s1=testA t1=111111 debug3 t1=111111 s1=testA Visual C(visual studio 2012 or 2013) d:\users\work\vc>wsttes debug0 s1=testA debug1 t1=111111 debug2 s1=testA t1=111111 debug3 t1=111111 s1=(null)  ←ここだけ異常? HP-UX ansi-C hp-ux % wsttes debug0 s1=testA debug1 t1=111111 debug2 s1=testA t1=111111 debug3 t1=111111 s1=testA */

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

  • ベストアンサー
回答No.2

time_tは2038年問題の対処として64bitに拡張された処理系が多くなっています。 time_tが64bit、intが32bitの場合、printfの書式として"%d"を指定してtime_tの値を渡すと、printfはtime_tの最初の32bitだけを整数として処理して、残りの32bitが残った状態になります。"%d"に続けて他の書式を指定していると、printfは残った32bit分のデータが次の書式のデータだとして処理するため、データがずれて正しい表示ができなくなります。 printfの書式の最後がtime_tのデータの場合は、32bit分残ったデータがあっても使われないだけなので、動作に支障がないように見えます。

yohmi88
質問者

お礼

ご回答ありがとうございます。これで解決しました。 vcは他のC 言語とは実装が違っていたのですね。 恥ずかしながら、64bitの可能性を失念していました。 sizeof()で確認しておくべきでした。 本当にありがとうございます。

その他の回答 (1)

  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.1

異常動作ではありません。 time_t型を"%d"で出力しようとしているからです。 time_t型がint型とサイズか同じか調べてみてください。 HP-UXが動作しているコンピュータのCPUはItanium系ですか?

yohmi88
質問者

お礼

ご回答ありがとうございます。 vcのTime_tが64bitであることに気づいていませんでした。 HPーUXはご想像の通りItaniumで動いています。

関連するQ&A

  • C言語 構造体 2

    三つの構造体α、β、γの実数部、虚数部の値(実数)をそれぞれ入力し、 (α+γ)(γ+β)を求めて表示せよ。 ただし、複素数を、実数部と虚数部に対応するメンバで構成される構造体として表し、複素数の加算用関数c_add()と乗算用関数c_mul()を作成して、これを利用すること。 これらの関数は、sとtを複素数を表す構造体としたとき、c_add(s,t)、c_mul(s,t)と呼び出すと、それぞれ戻り値として、sとtを加算、または乗算した結果である複素数の構造体を返すものとする。 という問題なのですが。。。。 #include<stdio.h> int main(void){ struct complex{ double real; double imaginary; }; struct complex[3]; double real; double imag; printf("α= "); scanf("%d,&real); scanf(%d,&imag); printf("β= "); scanf("%d,&real); scanf(%d,&imag); printf("γ="); scanf("%d,&real); scanf(%d,&imag); (α+γ)=c_add(α,γ); (β+γ)=c_add(β,γ); (α+γ)(β+γ)=c_mul(α+γ,β+γ) result=(α+γ)(β+γ) printf("result= "); まで友達と考えてみたのですが、このあとどうしたらいいのかわかりません>< どなたかお教えください。。お願いします。。。

  • C言語での構造体

    C言語の構造体で配列を扱うとき、 struct ○○{  char ○○[○] とすれば出来ますが、同じようにして構造体で二次元配列を扱うことは出来ますか? 一度組んでみたのですが、 #include<stdio.h> struct aaa{ int no; char name[128]; char y_name[128]; char n_name[128]; char s_name[128][128]; }; int main(void){ int i; struct aaa iryo[99]; printf("入力前\n"); /* 構造体配列に scanf()でデータを入力 */ for(i = 0; i < 3; i++) { // printf("input...\n"); scanf("%d", &iryo[i].no); scanf("%s", iryo[i].name); scanf("%s", iryo[i].y_name); scanf("%s", iryo[i].n_name); scanf("%s", iryo[i].s_name); } printf("入力後\n"); printf("出力前\n"); /* 入力データの確認 */ for(i = 0; i < 3; i++) { printf("番号:%02d 内容:%s Y分岐:%s N分岐:%s 他分岐:%s\n", iryo[i].no, iryo[i].name, iryo[i].y_name, iryo[i].n_name, iryo[i].s_name); } printf("出力後\n"); printf("%d",sizeof(struct aaa)); return 0; } としたら、エラーは出ませんが、実行すると何も表示されませんでした。

  • 構造体での質問!

    a.outの後にid ログイン名 ファミリーネーム ファーストネームを格納して出力するコードを 書いたのですが、これを a.out 5 のように書いて任意の人数の情報を格納して出力するものに したいのですが、↓をどうすればよいのでしょうか?お願いします!! #include <stdio.h> #include <string.h> structstudent { intid; char login[16]; char first[16]; char family[16]; }; intmain(intargc, char *argv[]) { structstudent st, *sp; if (argc!= 5) { printf("usage: %s[id] [login] [Family name] [First name]¥n", argv[0]); exit(‐1); } st.id= atoi(argv[1]); strcpy(st.login, argv[2]); strcat(st.first, argv[3]); strcpy(st.family, argv[4]); sp=&st; printf("id=%d¥n", sp‐>id); printf("loginname=%s¥n", sp‐>login); printf("Name=%s%s¥n", sp‐>first, sp‐>family); }

  • 構造体の使い方

    構造体の基本的な使い方を練習しようと思ったのですが、 なかなかスムーズにいきません。 p.d=10; の部分がおかしいようなのですが、色々試してもコンパイルできませんでした。 正しい使い方を教えていただけないでしょうか ソース ↓ #include<stdio.h> struct type{ int a; float b;  double c; }var,*p; main(){ c=9.87;      p=&var; p.d=10; p->b=1.2; printf("int:%d\n",*p); printf("float:%.1f\n",&p); printf("double:%.3lf\n",c); return 0; }

  • C言語の構造体について

    ご質問があります。 現在C言語について学習しているのですが、構造体を勉強しているときに下記のようなコードを作ったのですが storage size of 'mydata' isn't known というエラーが出てきてしまいます。 どこが間違っているのかがわかりません。 ご指南ご指導して頂けると助かります。 以下コード int main(void){ struct data mydata; mydata.name = "Yamada"; mydata.age = 30; mydata.height=173; mydata.weight = 65.4; printf("name = %s\n",mydata.name); printf("age = %d\n",mydata.age); printf("height = %d\n",mydata.height); printf("weight = %1f\n",mydata.weight); return EXIT_SUCCESS; }

  • ファイル情報の「月」の値を整数値で取得するには?

    こんにちは。私は30代の男性です。 下記のサイトに載っていたコーディングなのですが、 http://okuyama.mt.tama.hosei.ac.jp/unix/C/slide93-1.html 「ctime(&filestat.st_mtime)」で取得した「Sat Apr 5」の「月」の値を整数で取得する方法を 考えています(例えば、「Sat 4 5」という感じで)。 何かいい方法はないでしょうか?アドバイスを頂けるとありがたいです。 よろしくお願いします。 #include <sys/types.h> /* stat(), struct stat */ #include <sys/stat.h> /* stat(), struct stat */ #include <stdio.h> /* fprintf(), printf() */ #include <errno.h> /* errno */ #include <string.h> /* strerror() */ #include <stdlib.h> /* exit() */ #include <time.h> /* time_t, ctime() */ int main(void) { struct stat filestat; char path[] = "/path/to/file"; time_t dtime; if(stat(path, &filestat) == -1) { fprintf(stderr, "* Error (%d) [stat: %s]\n", errno, strerror(errno)); exit(errno); } printf("Size: %ld\n", (long)filestat.st_size); printf("Last accessed: %ld, %s", filestat.st_atime, ctime(&filestat.st_atime)); printf("Last modified: %ld, %s", filestat.st_mtime, ctime(&filestat.st_mtime)); dtime = filestat.st_atime - filestat.st_mtime; printf("%ld\n", dtime); exit(0); } 実行例です。 Size: 86555 Last accessed: 1049485323, Sat Apr 5 04:42:03 2003 Last modified: 1049428803, Fri Apr 4 13:00:03 2003 56520

  • 配列から構造体へデータコピー

    配列から構造体へデータのコピーをしたいのですが、 構造体のメンバがビットフィールドで構成されている時の処理がわかりません。 --------test.c----------- #include <stdio.h> #include <string.h> typedef struct{ unsigned char aaa :1; unsigned char bbb :1; unsigned char ccc :1; unsigned int ddd :13; unsigned char eee :2; unsigned char fff :2; unsigned char ggg :4; }test_t; int main(void) { test_t test_t; unsigned char data[]={0x5F, 0xFE, 0x1C}; memcpy(&test_t, data, 4); printf("aaa = %X\n", test_t.aaa); printf("bbb = %X\n", test_t.bbb); printf("ccc = %X\n", test_t.ccc); printf("ddd = %d\n", test_t.ddd); printf("eee = %X\n", test_t.eee); printf("fff = %X\n", test_t.fff); printf("ggg = %X\n", test_t.ggg); return 0; } ------期待出力--------- aaa = 0 bbb = 1 ccc = 0 ddd = 1FFE eee = 0 fff = 1 ggg = 12 「test.c」を実行した時に「期待出力」のような出力を期待していたのですが、実際には aaa = 1 bbb = 1 ccc = 1 ddd = 1 eee = 0 fff = 0 ggg = 0 と表示されてしまいます。 ビットフィールドで構成された構造体に、配列の値をそのままあてる事は出来ないのでしょうか? 出来るだけ、マスクやシフト演算を使用しないで、配列からビット単位で値を抽出したいのですが・・・

  • Visual C++ Express Edition でもprintf

    Visual C++ Express Edition でもprintfを使いたい 私は、Visual C++ 2008 Express Editionを使っています。  以前はVisual Studio 2005 Professionalを使っていました。 今まではプログラムを走らせている間の変数の変化を見るために、 printf関数を使って「出力」ウィンドウに数値を表示させていました。 Visual C++ 2008 Express Editionに変更してから、 同一のソースコードをコンパイル、実行しても printf文で記述した出力内容を「出力」ウィンドウに表示させることができません。 これは、Express Edition特有のものでしょうか? printfを使って変数を表示できる方法があれば教えてください。 よろしくお願いします。

  • 構造体の構造体 引数

    構造体の中の構造体の関数の引き渡し方法がわかりません。 下記ソースで試したのですが、うまくいきませんでした。 助言お願いいたします。 //repo.c #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #define NUM 20 #define MAX 15 struct seiseki{ float shu[3]; }; struct seito{ char name[NUM]; int age; struct seiseki kekka; }; void input(struct seito *p); void s_input(struct seiseki *p); void ss_input(struct seiseki *data); int main(){ int i; struct seito data[2]; for(i=0;i<2;i++){ printf("------------------------------\n"); printf("%d人目",i+1); input(&data[i]); } printf("%f\n",data[0].kekka.shu[0]); printf("%f\n",data[0].kekka.shu[1]); printf("%f\n",data[0].kekka.shu[2]); //data[1]に格納できない。 printf("%f\n",data[1].kekka.shu[0]); printf("%f\n",data[1].kekka.shu[1]); printf("%f\n",data[1].kekka.shu[2]); return 0; } void input(struct seito *p){ printf("名前->"); scanf("%s",p->name); printf("年齢->"); scanf("%d",p->age); s_input(&(p->kekka)); } void s_input(struct seiseki *data){ printf("国語->"); ss_input(data); printf("算数->"); ss_input(data); printf("英語->"); ss_input(data); } //下記関数で成績をchar型で受け取り、数値化したい。 void ss_input(struct seiseki *data){ char p[100]; int i=0; static int o=0; scanf("%s",p); while( p[i] != '\0'){ if(isdigit(p[i])==0){ printf("再入力してください"); scanf("%s",p); } i++; } data->shu[o]=atof(p); printf("%f\n",data->shu[o]); o++; }

  • [C言語]トラバースするプログラム(linux)

    linux(ubuntu11.04)でコマンドラインからもらったディレクトリをトラバースするプログラムを作りたいんですがうまくいきません。 一応書けたのですがどうも予想と違う動きをしてしまいます。 #include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<sys/stat.h> #include<dirent.h> #include<string.h> static void do_traverse(char *patht, int t); int main(int argc, char *argv[]) { int i; if(argc<2) { fprintf(stderr,"%s: no arguments\n",argv[0]); exit(1); } for(i=1;i<argc;i++) { do_traverse(argv[i],0); } return 0; } static void do_traverse(char *path, int t) { DIR *d; struct dirent *ent; int i; d=opendir(path); if(!d) { perror(path); exit(1); } while((ent=readdir(d))!=NULL) { struct stat st; if(lstat(ent->d_name,&st)<0) { perror(ent->d_name); exit(1); } for(i=0;i<t;i++) { printf(" "); } printf("%s\n",ent->d_name); if((strcmp(".",ent->d_name))==0 || (strcmp("..",ent->d_name))==0 || S_ISLNK(st.st_mode)) { continue; } if(S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode)) { do_traverse(ent->d_name,t+1); } } closedir(d); } 例えばディレクトリaにファイルbとディレクトリcがあり、ディレクトリcの中にはファイルdとディレクトリeがあり、ディレクトリeの中にはファイルfがあるとします。 僕の理想では $./traverse a とすると .. . b c .. . d e .. . f となるはずなんですが(表示の順番は適当です)、実際は b .. . c となってしまいうまくトラバースしてくれません どうしてこうなるかわかりません 誰か助けてください お願いします