C言語の変数について

このQ&Aのポイント
  • C言語の変数について教えていただきたいです。バイト数制限はないのでしょうか?
  • C言語で変数にバイト数制限はないのかについて教えてください。
  • C言語で変数のバイト数制限について教えてください。
回答を見る
  • ベストアンサー

C言語の変数について

C言語の変数について教えていただきたいです。 C言語で下記のような設定をした場合、変数A、Bに設定する値にはバイト数制限 はないのでしょうか? バイト数制限がなくなる場合、なぜそうなるのかを教えていただきたいです。 よろしくお願いします。 #include <stdio.h> void test( char **B); int main( int argc, char *argv[] ) { char *A = NULL; char *B = NULL; A = argv[1]; test( B ); return 0; } void test( char **B ) { strcpy(B, "ABCD"); return 0; }

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

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

このソースだと、 Aのポインタは、NULLで初期化後に、コマンドライン引数1のポインタをセット。 Bのポインタ(格納するメモリーの場所)は、NULLで初期化 Bのポインタをtest()関数に引き渡し (なのに、test()側では、それをポインタのポインタで受取り) そのNULLの位置は格納場所として確保されていないので"ABCD"をコピーした時点で、セグメントエラー。(コンパイラやOS次第だけど) なので、 A,Bにはバイト数制限はありますか?  という問いついては、 ・Aは、コマンドライン引数の1つ目を示すargv[1]をポインタを使っていて  これは、実行時に自動でメモリー確保されているので、  バイト数制限は、コマンドライン実行時の引数1の文字の長さということになります。 ・Bは、そもそもメモリーが確保されていないので、1バイトさえない、ということになります。 なお、 10行目 test( B ); ↓ test( &B ); 16行目 strcpy(B,"ABCD" ); ↓ *B = malloc(strlen("ABCD")+1); strcpy ( *B , "ABCD");  もしくは、1行で *B = strdup("ABCD"); と、メモリーを確保してからコピーするようにすれば、Bにバイト制限はなくなります。

OMEGA_3210_50
質問者

お礼

お礼が遅れてすみません。 わかりやすく解説していただきありがとうございます。

その他の回答 (5)

  • teuaitou
  • ベストアンサー率32% (10/31)
回答No.5

AもBもcharポインターを宣言しているだけです。データを格納する領域は確保されてませんから、バイト数の制限などあるわけ無いですよ。 ポインターって理解されたますか?メモリ上の点(アドレス)を指し示すだけの機能しか無いですよ。なので、ポインタ変数を宣言すると、そのアドレスを格納するための領域しか確保されないですよ。そして、初期化して無けれなそのポインタ変数の内容は不定値です。

OMEGA_3210_50
質問者

お礼

ご回答ありがとうございます。 すみません、ポインタの理解があまりできておらず稚拙な質問をしてしまいました。

  • Wap58
  • ベストアンサー率33% (29/87)
回答No.4

訂正、Apple LLVM version 7.3.0 (clang-703.0.31) ./a.out Q これで動きますね、スンマセン #include <stdio.h> #include <string.h> void test(char *B){ printf("test %s\n",B); if(B != NULL){ strcpy(B,"QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"); printf("strcpy %s\n",B); } } int main(int argc,char *argv[]){ char *A = NULL; A = argv[1]; printf("main %s\n",A); test(A); return 0; }

  • Wap58
  • ベストアンサー率33% (29/87)
回答No.3

文脈から自然解釈しました、間違えてたらスルーして *argv[]は配列のポインタを受け取ります char argv[] = "AAA_1BBB_2CCC_3";<=これのポインタ 配列は初期化の時のみメモリーを自動で確保します #include <stdio.h> void test(char *B){ printf("%s\n",B); } int main( int argc, char *argv[] ){ char *A = NULL; A = argv[1]; printf("%s\n",A); test(A); return 0; }

OMEGA_3210_50
質問者

お礼

Aに関しては、領域が確保されているargのポインタを設定しているため、 正常に使えているということですね。 ありがとうございます。

  • chie65535
  • ベストアンサー率43% (8519/19367)
回答No.2

C言語の「メモリ管理」は、基本的に「プログラマが自分で行なう」事になります。 言語そのものは「指示されたアドレスに、有効なメモリが存在するかどうか、一切、関知しない」のです。 例えば「5バイト分しか無い場所に8バイト書き込む処理」をしても、そのまま「警告無しに動作」します(そして「メモリを壊す」でしょう) 例えば「ROM領域になっていて、書き込みが出来ないメモリに書き込む処理」をしても、そのまま「警告無しに動作」します(そして「不正なメモリアクセス」の実行時例外が起きるでしょう) なので「そこに書き込めるメモリがあるかどうか?」や「何バイト分の書き込めるメモリがあるのか?」は「プログラムを書く人が自分で管理しないといけない」のです。 C言語が「OSそのものや、デバイスドライバの開発言語になっている理由」は「メモリの管理を自分で行なえるから」です。言い換えると「どこのメモリであっても自由に読み書き可能だから」なのです。

OMEGA_3210_50
質問者

お礼

なるほど。 やはり私の記述では領域を確保していないため、メモリを壊している(想定外の領域を使用している。)ということですね。 ありがとうございます。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

私のところでコンパイルしたところ、警告がいくつか出ました。 その警告を無視して実行したところ、落ちました。 落ちた最大の原因は、変数BにNULLが入っているにもかかわらず 強引に"ABCD"をコピーしようとしたところにあると思います。 Bには、"ABCD"を格納できるだけの適切な領域が必要であるはずです。

OMEGA_3210_50
質問者

お礼

なるほど。 やはり領域を確保しないとダメということですね。 ありがとうございます。

関連するQ&A

  • C言語についてなのですが・・・

    さきほども上げたのですがカテゴリが間違っていたのでもう一回書き込みました まだプログラムの勉強をはじめた初心者なのですが、 テキストファイルから文字を読みこみ、大文字ならば小文字に変換し辞書順に並びかえるプログラムを作っているのですがどうしてもうまくいきません。 例えばtest.txtに XXX YYY YY XX BBB aaa aa BB とあれば aa aaa bb bbb xx xxx yy yyy と表示されるよにしたいんです。 自分が作ったプログラむはこれです。 まだテキストファイルからでなくキーボードからの入力になっていますが・・・ #include<stdio.h> #include<stdlib.h> #include<string.h> #include <ctype.h> int soto( const void *x, const void *y); int main(int argc, char *argv[]){ FILE *input; char str1[1000]; int i, j; for (i = 1; i < argc; i++){ qsort(argv[i], 1000, sizeof( char *), soto); strcpy(str1, argv[i]); for(j = 0; j < 100; j++){ str1[j] = tolower( str1[j] ); } printf("%s\n", str1); } return 0; } int soto( const void *a, const void *b){ char *x, *y; x = (char*)a; y = (char*)b; return x-y; } これだと小文字にはなるんですがソートされずに表示されてしまいます・・・ どのようにすればいけるのかご指摘のほどおねがいします

  • C言語で文字列をかえす正しい書き方が知りたいです?

    C言語で次の警告が表示されます。 文字列を返したいのですが、正しい書き方はどのようにすれば良いのでしょうか? jci.h(20) : warning C4172; ローカル変数またはテンポラリのアドレスを返します。 char *test(char *a, int b) { char str[BUFSIZ]; return str; <------ }

  • C言語の課題に取り組んでいるんですが・・・

    まだプログラムの勉強をはじめた初心者なのですが、 テキストファイルから文字を読みこみ、大文字ならば小文字に変換し辞書順に並びかえるプログラムを作っているのですがどうしてもうまくいきません。 例えばtest.txtに XXX YYY YY XX BBB aaa aa BB とあれば aa aaa bb bbb xx xxx yy yyy と表示されるよにしたいんです。 自分が作ったプログラむはこれです。 まだテキストファイルからでなくキーボードからの入力になっていますが・・・ #include<stdio.h> #include<stdlib.h> #include<string.h> #include <ctype.h> int soto( const void *x, const void *y); int main(int argc, char *argv[]){ FILE *input; char str1[1000]; int i, j; for (i = 1; i < argc; i++){ qsort(argv[i], 1000, sizeof( char *), soto); strcpy(str1, argv[i]); for(j = 0; j < 100; j++){ str1[j] = tolower( str1[j] ); } printf("%s\n", str1); } return 0; } int soto( const void *a, const void *b){ char *x, *y; x = (char*)a; y = (char*)b; return x-y; } これだと小文字にはなるんですがソートされずに表示されてしまいます・・・ どのようにすればいけるのかご指摘のほどおねがいします

  • 関数へ引数を渡す時・・・(C言語)

    Cを始めたばかりです。 レベルの低い質問だと思いますがお願いします。 【ソース】 /* a1.c */ #include <stdio.h> void aaa(char); int main( int argc, char *argv[] ) { char box[] = "test"; aaa(box); return 0; } /* a2.c */ #include <stdio.h> void aaa(char box) { printf( "%s",box ); } 【質問】 変数boxの中身を関数aaaに渡したいだけですが、 上記ソースをコンパイルすると、a1.cの aaa(box) の部分でエラーが出てしまいます。 どうもデータ型(ポインタ?)がまずいようですが、 何が問題なのでしょうか? 御回答宜しくお願い致します。

  • 変数操作(C言語)

    C言語でプログラムを書いてます。 char1[0]:1 char1[1]:5   ↓ char2[0]:1 char2[1]:NULL char2[2]:NULL char2[3]:NULL char2[4]:5 char2[5]:NULL という風に値の順番と配列の順番を別の変数で一緒にしたいのです。1から5までの値はNULL、また5以降はNULLといったように値を格納したいのです。 こういったロジックの組み方のご教授願います。 また値が2、4でも対応できるような(どんな数でも)ものでお願いします。(↓例) char1[0]:2 char1[1]:4   ↓ char2[0]:NULL char2[1]:2 char2[2]:NULL char2[3]:4 char2[4]:NULL char2[5]:NULL よろしくお願い致します。

  • C言語計算プログラム

    Cの計算プログラム 下のプログラムを (1)上位桁の不要な0を表示しない (2)3つの数を計算できるようにする (3)0が入力されるまでは入力を受け付けて加算を繰り返す プログラムに改造する方法を教えてください。 #include <stdio.h> #define MAXDIGIT 70 void reset(char*,int); void input(char*,int); void add(char*,char*,char*,int); void add_digit(char ,char ,char ,char* ,char* ); void display(char* ,char* ,char* ,int ); void lineprint(char ,char* ,int ); void linedraw(char ,int ); int main(void) { char a[MAXDIGIT],b[MAXDIGIT],c[MAXDIGIT]; reset(a,MAXDIGIT); reset(b,MAXDIGIT); reset(c,MAXDIGIT); input(a,MAXDIGIT); input(b,MAXDIGIT); add(a,b,c,MAXDIGIT); display(a,b,c,MAXDIGIT); return 0;} void reset(char* buf,int maxdigit) { int i; for(i=0;i<maxdigit;i++) buf[i]=0; return;} void input(char* buf,int maxdigit) { char str[MAXDIGIT]; int i,j; printf("input data:"); scanf("%s",str); i=0; while(str[i]!='\0') i++; j=0; while(i>0){ buf[j]=str[i-1]-'0'; j++; i--; } return;} void add(char* a,char* b,char* c,int maxdigit) { int i; char carry_in,carry_out; i=0; carry_in=0; while(i<maxdigit) { add_digit(a[i],b[i],carry_in,&c[i],&carry_out); carry_in=carry_out; i++;} return;} void add_digit(char a,char b,char carry_in,char* c,char* carry_out) { *c=(a+b+carry_in)%10; *carry_out=(a+b+carry_in)/10; return;} void display(char* a,char* b,char* c,int maxdigit) { lineprint(' ',a,maxdigit); lineprint('+',b,maxdigit); linedraw('-',maxdigit+1); lineprint(' ',c,maxdigit); return;} void lineprint(char c,char* line,int maxdigit) { int i,maxdigitlimit; maxdigitlimit=maxdigit-1; printf("%c",c); for(i=maxdigitlimit;i>=0;i--){ printf("%1d",line[i]); } printf("\n"); return;} void linedraw(char c,int length) { int i; for(i=0;i<length;i++) printf("%c",c); printf("\n"); return;}

  • C言語、fgetcを利用しファイルの内容を変数に

    C言語について質問です C言語のfgetcを利用しファイルの内容を変数にいれてそれを返す関数を作っているのですがうまくいきません <!--以下ソース--> char *file_get_contents(char *filename){ FILE *fp; int c; char *return_str; if((fp=fopen(filename,"r"))==NULL) return NULL; while((c=fgetc(fp))!=EOF ){ sprintf(return_str,"%c",c); } fclose(fp); return return_str; } 誰か理由と改善方法を教えてください!

  • C言語 動的なメモリの確保 実行できない

    malloc関数を使いメモリを確保しそこへ"ABCD"と記憶させ、ポインタ*Cを使い確保したメモリの内容を表示するプログラムです。 ********************************************* #include <stdio.h> #include <stdlib.h> int main(void) {   int i;   char *C;   C = (char *) malloc (sizeof(char) * 5);   C = "ABCD";   for(i = 0; i < 5; i++){     if(C[i] != NULL){       printf("%s", C[i]);    ←※エラー※     }   }   free(C);   return 0; } ********************************************* 正常にコンパイルできますが実行エラーになります。VCを使いF10のデバッグテストで※のところエラーになります。なぜなのでしょうか?

  • C言語のシェルプログラミングの課題が分かりません。

    C言語のシェルプログラミングを作れという課題で、以下のように作ったんですが、実行して何度かコマンドを入力した後、exitによって一発で終わらせることができません。どのように書き換えればいいか教えて下さい。 また、他にも書き換えた方がよいと思えるところがあったら是非教えて下さいm(_ _)m #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/wait.h> #include <sys/types.h> #include MAX_ARGS 10 #include MAX_LEN 100 extern char **environ; void child(int argc, char *argv[MAX_ARGS]); int main(void){ int argc, n = 0; int status; char input[MAX_LEN], *argv[MAX_ARGS], *cp; const char *delim = "\t\n"; while (1){ ++n; printf("$ "); fflush(stdout); if(fgets(input, sizeof(input), stdin) == NULL){ break; } cp = input; for(argc = 0; argc < MAX_ARGS; argc++){ if((argv[argc] = strtok(cp, delim)) == NULL) break; cp = NULL; } if(strcmp(argv[0], "exit") == 0){ exit(0); } pid_t pid = fork(); if(pid == -1){ perror("fork"); exit(1); }else if(pid == 0){ child(argc, argv); }else{ wait(&status); } } return 0; } void child(int argc, char *argv[MAX_ARGS]{ execvp(argv[0], argv); }

  • C言語 ソートについて

    #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { } bool is_at(char c) { } void justify(char line[], int n) { } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; } 上の雛形を使って文字列lineに含まれる@以外の文字を文字列の前の方に詰めていくプログラミングを作るという問題を解いていたのですが下のプログラミングまでは出来たのですが最後のjustifyの部分がわかりません 良ければ解答をお願いします #include <stdbool.h> #include <stdio.h> void swap(char *a, char *b) { char temp = *a; *a = *b; *b = temp; } bool is_at(char c) { if(c == '@') { return true; } else { return false; } } void justify(char line[], int n) { for(int i=0;i<n-1;i++) { } } int main(void) { char line[] = "a@b@@@c@@d@@@ef@@g"; size_t n = sizeof(line) - 1; justify(line, n); printf("%s\n", line); return 0; }

専門家に質問してみよう