LoginSignup
3
2

More than 1 year has passed since last update.

「@nobodytolove123 char*とchar[]についてのメモ」を検証(途中)仮説(193)

Last updated at Posted at 2019-08-15

@nobodytolove123 char*とchar[]についてのメモ

C言語の文字列変数のchar*とchar[]の違いを検証

一部を検証している。

確認後、いくつかの検証を追加してみる。

まず、コンパイルできる形にしてみる。

sample.c
/* https://qiita.com/nobodytolove123/items/d5f140ef4afb9ba7603b */
/* modified by Dr. Kiyoshi Ogawa @ https://qiita.com/kaizen_nagoya/items/0cd3518e680397580c7e */

#include <stdio.h>
int main(){

    char *literal  = "name"; 
    char stack[]   = "name"; 

    char _stack[] = "bar";
    char* _literal = "bar";

    printf("%p\n", stack);
    printf("%p\n", _stack);
    printf("%p\n", literal);
    printf("%p\n", _literal);


    ++literal;       
    --literal;       

    /* ++(*literal); */ 

    /* ++stack;    */
    ++(*stack);    

    printf("%c\n", literal[1]);
    printf("%c\n", stack[1]);
    printf("%c\n", *literal + 1);
    printf("%c\n", *stack + 1);
    return printf("sample.c¥n");
}

下の方に記録したスクリプトで実行

docker/ubuntu
# ./gcl.sh sample
$ clang sample.c
0x7ffc0e50036b
0x7ffc0e500367
0x402004
0x402009
a
a
o
p
sample.c

$ gcc sample.c
0x7ffe5914503b
0x7ffe59145037
0x402004
0x402009
a
a
o
p
sample.c

// ++(*literal); // 定数領域の文字列に対してインクリメントを行うため、実行時エラー

本当だろうか。

docker/ubuntu
# ./gcl.sh sample2
$ clang sample2.c
0x7ffe81c7252b
0x7ffe81c72527
0x402004
0x402009
Segmentation fault

$ gcc sample2.c
0x7fffc3c9909b
0x7fffc3c99097
0x402004
0x402009
Segmentation fault

本当だった。

// ++stack; // 配列に対してインクリメントは不可

docker/ubuntu
clang sample3.c
sample3.c:20:5: error: cannot increment value of type 'char [5]'
    ++stack;    
    ^ ~~~~~
1 error generated.

$ gcc sample3.c
sample3.c: In function 'main':
sample3.c:20:5: error: lvalue required as increment operand
   20 |     ++stack;
      |     ^~

コンパイルエラーになる。

他に検討することはないだろうか。

相互に代入した時はどうなるだろう。

samplea.c
/* https://qiita.com/nobodytolove123/items/d5f140ef4afb9ba7603b */
/* modified by Dr. Kiyoshi Ogawa @ https://qiita.com/kaizen_nagoya/items/0cd3518e680397580c7e */
#include <stdio.h>
int main(){

    char *literal  = "name"; 
    char stack[]   = literal; 

    char _stack[] = "bar";
    char* _literal = _stack;

 /*   printf("%p\n", stack); */
    printf("%p\n", _stack);
    printf("%p\n", literal);
    printf("%p\n", _literal);


    ++literal;       
    --literal;       

    /* ++(*literal); */ 

    /* ++stack;    */ 
 /*   ++(*stack);    */

    printf("%c\n", literal[1]);
/*    printf("%c\n", stack[1]); */
    printf("%c\n", *literal + 1);
/*    printf("%c\n", *stack + 1); */
	return printf("samplea.c\n");
}
docker/ubuntu
# ./gcl.sh samplea
$ clang samplea.c
samplea.c: In function 'main':
samplea.c:5:22: error: invalid initializer
    5 |     char stack[]   = literal; //
      |                      ^~~~~~~

$ gcc samplea.c
samplea.c: In function 'main':
samplea.c:5:22: error: invalid initializer
    5 |     char stack[]   = literal; //
      |                      ^~~~~~~

char stack[]で宣言したものにchar * literalで宣言した変数を代入しようとするとコンパイルエラーになる

逆の char* _literal = _stack;はコンパイルエラーにならない。実行してみた。

docker/ubuntu
# ./gcl.sh sampleb
$ clang sampleb.c
0x7fffb6db68dc
0x402004
0x7fffb6db68dc
a
o
samplea.c

$ gcc sampleb.c
0x7ffeec7ec2bc
0x402004
0x7ffeec7ec2bc
a
o

const

定数はconst。ROMは定数領域。定数領域に配置するのはC言語ではなく、Locator。

c*sampleb.c
/* https://qiita.com/nobodytolove123/items/d5f140ef4afb9ba7603b */
/* modified by Dr. Kiyoshi Ogawa @ https://qiita.com/kaizen_nagoya/items/0cd3518e680397580c7e */

#include <stdio.h>

int main(){
    

    const char *literal  = "name"; 
    const char stack[]   = "name";

    char _stack[] = "bar";
    char* _literal = "bar";

    printf("%p\n", stack);
    printf("%p\n", _stack);
    printf("%p\n", literal);
    printf("%p\n", _literal);


    ++literal;       
    --literal;       

    /* ++(*literal); */ 

    /* ++stack;    */ 
    /* ++(*stack); */   

    printf("%c\n", literal[1]);
    printf("%c\n", stack[1]);
    printf("%c\n", *literal + 1);
    printf("%c\n", *stack + 1);
    return printf("sample6.c\n");
}

各種標準対応でコンパイルしてみた。

docker/ubuntu
# ./gclall.sh sample6
$ clang -std=c17 sample6.c -o sample6l2017
0x7ffee12fce1b
0x7ffee12fce17
0x402004
0x402009
a
a
o
o
sample6.c

$ gcc -std=c17 sample6.c -o sample6g2017
0x7ffdff4c8b9b
0x7ffdff4c8b97
0x402004
0x402009
a
a
o
o
sample6.c
$ clang -std=c11 sample6.c
0x7fffbb8bd4eb
0x7fffbb8bd4e7
0x402004
0x402009
a
a
o
o
sample6.c

$ gcc -std=c11 sample6.c
0x7ffdcda63eab
0x7ffdcda63ea7
0x402004
0x402009
a
a
o
o
sample6.c
$ clang -std=c99 sample6.c
0x7ffff78edd5b
0x7ffff78edd57
0x402004
0x402009
a
a
o
o
sample6.c

$ gcc -std=c99 sample6.c
0x7fff2d72066b
0x7fff2d720667
0x402004
0x402009
a
a
o
o
sample6.c
$ clang -std=c90 sample6.c
0x7fffdd0c337b
0x7fffdd0c3377
0x402004
0x402009
a
a
o
o
sample6.c

$ gcc -std=c90 sample6.c
0x7ffe60b9f20b
0x7ffe60b9f207
0x402004
0x402009
a
a
o
o
sample6.c

docker hubに登録

docker hubの登録したイメージを利用するには、

$ docker run -v /Users/administrator/Downloads/work:/home/work  -it kaizenjapan/samplec   /bin/bash 
```
administratorのところを実際のuser名。Downloadsのしたにworkが作ってあって、dockerで利用したいファイルが入っているか、ホストOSで編集したいファイルの置き場。

上記システム構築まで

``````shell-session:macOS
$ docker run -v /Users/ogawakiyoshi/Downloads/work:/home/work  -it gcc   /bin/bash 
```

```shell-session:docker/ubuntu
# apt update; apt -y upgrade
# apt install vim wget clang gdb apt-utils
# cd /home
# mkdir c
# cd c
```
workフォルダに必要なファイルを作ってcフォルダにcpして作業した。

```shell-session:macOS
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
090c29f6d2ae        gcc                 "/bin/bash"         5 hours ago         Up 5 hours                                   ecstatic_mccarthy
$ docker commit 090c29f6d2ae  kaizenjapan/samplec
$ docker push kaizenjapan/samplec
```

#C言語規格類での関連事項を記録。

N2176 Programming Language C2018 (aka C2017)
https://qiita.com/kaizen_nagoya/items/858b65bd65550cd63d6d
>p.104
EXAMPLE 8 The declaration
char s[] = "abc", t[3] = "abc";
defines “plain” char array objects s and t whose elements are  initialized with character string literals. This declaration is identical to
char s[] = { ’a’, ’b’, ’c’, ’\0’ },
t[] = { ’a’, ’b’, ’c’ };
The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";
defines p with type “pointer to char” and initializes it to point to an object with type “array of char” with length 4 whose elements are initialized with a character string literal. If an attempt is made to use p to modify the contents of the array, the behavior is undefined.

# 参考資料(reference)

コンパイル用shell script C版(clangとgcc)とC++版(clang++とg++)
https://qiita.com/kaizen_nagoya/items/74220c0577a512c2d7da

```sh:gcl.sh
#!/bin/sh
#(c) Dr. Kiyoshi Ogawa
echo "$ clang $1.c"
clang $1.c -o $1l
if [  -e $1l ]; then
./$1l 
fi
echo "\r"
echo "$ gcc $1.c"
gcc $1.c -o $1g
if [  -e $1g ]; then
./$1g 
fi
```
4種類の標準準拠でのコンパイル用は

```sh:gclall.sh
#!/bin/sh
#(c) Dr. Kiyoshi Ogawa
echo "$ clang -std=c17 $1.c -o $1l2017"
clang $1.c -std=c17 -o $1l2017
if [  -e $1l2017 ]; then
./$1l2017 
fi
echo "\r"
echo "$ gcc -std=c17 $1.c -o $1g2017"
gcc $1.c -std=c17  -o $1g2017
if [  -e $1g2017 ]; then
./$1g2017 
fi
echo "$ clang -std=c11 $1.c"
clang $1.c -std=c11 -o $1l2011
if [  -e $1l2011 ]; then
./$1l2011 
fi
echo "\r"
echo "$ gcc -std=c11 $1.c"
gcc $1.c -std=c11 -o $1g2011
if [  -e $1g2011 ]; then
./$1g2011 
fi
echo "$ clang -std=c99 $1.c"
clang $1.c -std=c99 -o $1l1999
if [  -e $1l1999 ]; then
./$1l1999
fi
echo "\r"
echo "$ gcc -std=c99 $1.c"
gcc $1.c -std=c99  -o $1g1999
if [  -e $1g1999 ]; then
./$1g1999
fi
echo "$ clang -std=c90 $1.c"
clang $1.c -std=c90 -o $1l1990
if [  -e $1l1990 ]; then
./$1l1990
fi
echo "\r"
echo "$ gcc -std=c90 $1.c"
gcc $1.c -std=c90  -o $1g1990
if [  -e $1g1990 ]; then
./$1g1990
fi
```

3
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2