@nobodytolove123 char*とchar[]についてのメモ
https://qiita.com/nobodytolove123/items/d5f140ef4afb9ba7603b
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
```
### 最後までおよみいただきありがとうございました。
いいね 💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.
Please press the like icon 💚 and follow me for your happy life.