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

@nobodytolove123 char*とchar[]についてのメモ
https://qiita.com/nobodytolove123/items/d5f140ef4afb9ba7603b
>C言語の文字列変数のchar*とchar[]の違いを検証

一部を検証している。

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

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

```c: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");
}
```
下の方に記録したスクリプトで実行

```shell-session: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); // 定数領域の文字列に対してインクリメントを行うため、実行時エラー

本当だろうか。

```shell-session:docker/ubuntu
# ./gcl.sh sample2
$ clang sample2.c
0x7ffe81c7252b
0x7ffe81c72527
0x402004
0x402009
Segmentation fault

$ gcc sample2.c
0x7fffc3c9909b
0x7fffc3c99097
0x402004
0x402009
Segmentation fault
```
本当だった。

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

```shell-session: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;
      |     ^~
```
コンパイルエラーになる。

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

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

```c: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");
}
```

```shell-session: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;はコンパイルエラーにならない。実行してみた。

```shell-session: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");
}
```
各種標準対応でコンパイルしてみた。


```shell-session: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の登録したイメージを利用するには、

``````shell-session
$ 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
```
４種類の標準準拠でのコンパイル用は

```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
```
### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.